@xeokit/xeokit-sdk 2.6.72 → 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.
- package/dist/xeokit-sdk.cjs.js +767 -295
- package/dist/xeokit-sdk.es.js +762 -296
- package/dist/xeokit-sdk.es5.js +535 -525
- package/dist/xeokit-sdk.min.cjs.js +8 -8
- package/dist/xeokit-sdk.min.es.js +8 -8
- package/dist/xeokit-sdk.min.es5.js +7 -7
- package/package.json +1 -1
package/dist/xeokit-sdk.cjs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* xeokit-sdk v2.6.
|
|
3
|
-
* Commit:
|
|
4
|
-
* Built: 2025-
|
|
2
|
+
* xeokit-sdk v2.6.73
|
|
3
|
+
* Commit: 3b3bb2ad8abfdf189cf4ba7f67d6798375772b7b
|
|
4
|
+
* Built: 2025-04-10T16:46:49.684Z
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
@@ -334,6 +334,7 @@ class ContextMenu {
|
|
|
334
334
|
* @param {Boolean} [cfg.enabled=true] Whether this ````ContextMenu```` is initially enabled. {@link ContextMenu#show} does nothing while this is ````false````.
|
|
335
335
|
* @param {Boolean} [cfg.hideOnMouseDown=true] Whether this ````ContextMenu```` automatically hides whenever we mouse-down or tap anywhere in the page.
|
|
336
336
|
* @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.
|
|
337
|
+
* @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````.
|
|
337
338
|
*/
|
|
338
339
|
constructor(cfg = {}) {
|
|
339
340
|
|
|
@@ -348,6 +349,7 @@ class ContextMenu {
|
|
|
348
349
|
this._itemMap = {}; // Items mapped to their IDs
|
|
349
350
|
this._shown = false; // True when the ContextMenu is visible
|
|
350
351
|
this._nextId = 0;
|
|
352
|
+
this._parentNode = cfg.parentNode || document.body;
|
|
351
353
|
|
|
352
354
|
/**
|
|
353
355
|
* Subscriptions to events fired at this ContextMenu.
|
|
@@ -356,12 +358,12 @@ class ContextMenu {
|
|
|
356
358
|
this._eventSubs = {};
|
|
357
359
|
|
|
358
360
|
if (cfg.hideOnMouseDown !== false) {
|
|
359
|
-
|
|
361
|
+
this._parentNode.addEventListener("mousedown", (event) => {
|
|
360
362
|
if (!event.target.classList.contains("xeokit-context-menu-item")) {
|
|
361
363
|
this.hide();
|
|
362
364
|
}
|
|
363
365
|
});
|
|
364
|
-
|
|
366
|
+
this._parentNode.addEventListener("touchstart", this._canvasTouchStartHandler = (event) => {
|
|
365
367
|
if (!event.target.classList.contains("xeokit-context-menu-item")) {
|
|
366
368
|
this.hide();
|
|
367
369
|
}
|
|
@@ -665,7 +667,10 @@ class ContextMenu {
|
|
|
665
667
|
const groups = menu.groups;
|
|
666
668
|
const html = [];
|
|
667
669
|
|
|
668
|
-
|
|
670
|
+
const menuElement= document.createElement("div");
|
|
671
|
+
menuElement.classList.add("xeokit-context-menu", menu.id);
|
|
672
|
+
menuElement.style.zIndex = 300000;
|
|
673
|
+
menuElement.style.position = "absolute";
|
|
669
674
|
|
|
670
675
|
html.push('<ul>');
|
|
671
676
|
|
|
@@ -716,13 +721,10 @@ class ContextMenu {
|
|
|
716
721
|
}
|
|
717
722
|
|
|
718
723
|
html.push('</ul>');
|
|
719
|
-
html.push('</div>');
|
|
720
724
|
|
|
721
725
|
const htmlString = html.join("");
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const menuElement = document.querySelector("." + menu.id);
|
|
726
|
+
menuElement.innerHTML = htmlString;
|
|
727
|
+
this._parentNode.appendChild(menuElement);
|
|
726
728
|
|
|
727
729
|
menu.menuElement = menuElement;
|
|
728
730
|
|
|
@@ -756,7 +758,7 @@ class ContextMenu {
|
|
|
756
758
|
const item = groupItems[j];
|
|
757
759
|
const itemSubMenu = item.subMenu;
|
|
758
760
|
|
|
759
|
-
item.itemElement =
|
|
761
|
+
item.itemElement = this._parentNode.querySelector(`#${item.id}`);
|
|
760
762
|
|
|
761
763
|
if (!item.itemElement) {
|
|
762
764
|
console.error("ContextMenu item element not found: " + item.id);
|
|
@@ -11659,9 +11661,28 @@ const tmpVec4b = math.vec4();
|
|
|
11659
11661
|
const tmpVec4c = math.vec4();
|
|
11660
11662
|
const tmpVec4d = math.vec4();
|
|
11661
11663
|
const tmpMat4 = math.mat4();
|
|
11664
|
+
const tmpRay = {
|
|
11665
|
+
origin: math.vec3(),
|
|
11666
|
+
direction: math.vec3()
|
|
11667
|
+
};
|
|
11662
11668
|
|
|
11663
11669
|
const nop = () => { };
|
|
11664
11670
|
|
|
11671
|
+
const planeIntersect$1 = function(p0, n, origin, direction) {
|
|
11672
|
+
const t = (p0 - math.dotVec3(origin, n)) / math.dotVec3(direction, n);
|
|
11673
|
+
if (t < 0)
|
|
11674
|
+
{
|
|
11675
|
+
return null;
|
|
11676
|
+
}
|
|
11677
|
+
else
|
|
11678
|
+
{
|
|
11679
|
+
const worldPos = math.vec3();
|
|
11680
|
+
math.mulVec3Scalar(direction, t, worldPos);
|
|
11681
|
+
math.addVec3(origin, worldPos, worldPos);
|
|
11682
|
+
return worldPos;
|
|
11683
|
+
}
|
|
11684
|
+
};
|
|
11685
|
+
|
|
11665
11686
|
function transformToNode(from, to, vec) {
|
|
11666
11687
|
const fromRec = from.getBoundingClientRect();
|
|
11667
11688
|
const toRec = to.getBoundingClientRect();
|
|
@@ -11923,9 +11944,15 @@ class Label3D {
|
|
|
11923
11944
|
this._mid = math.vec3();
|
|
11924
11945
|
this._end = math.vec3();
|
|
11925
11946
|
this._yOff = 0;
|
|
11926
|
-
this._betweenWires = false;
|
|
11927
11947
|
this.__visible = true;
|
|
11928
11948
|
|
|
11949
|
+
this._updatePos = () => {
|
|
11950
|
+
toClipSpace(camera, this._start, tmpVec4a);
|
|
11951
|
+
math.mulVec4Scalar(tmpVec4a, 1.0 / tmpVec4a[3]);
|
|
11952
|
+
toCanvasSpace(scene.canvas.canvas, parentElement, tmpVec4a, tmpVec2a);
|
|
11953
|
+
this._label.setPos(tmpVec2a[0], tmpVec2a[1]);
|
|
11954
|
+
};
|
|
11955
|
+
|
|
11929
11956
|
const setPosOnWire = (p0, p1, yOff) => {
|
|
11930
11957
|
p0[0] += p1[0];
|
|
11931
11958
|
p0[1] += p1[1];
|
|
@@ -11933,36 +11960,44 @@ class Label3D {
|
|
|
11933
11960
|
this._label.setPos(p0[0], p0[1] + yOff);
|
|
11934
11961
|
};
|
|
11935
11962
|
|
|
11936
|
-
this.
|
|
11937
|
-
|
|
11938
|
-
|
|
11963
|
+
this._updatePosBetween = () => {
|
|
11964
|
+
const visibleA = clipSegment(scene, parentElement, this._start, this._mid, tmpVec2a, tmpVec2b);
|
|
11965
|
+
const visibleB = clipSegment(scene, parentElement, this._end, this._mid, tmpVec2c, tmpVec2d);
|
|
11966
|
+
this._label.setCulled(! (visibleA || visibleB));
|
|
11967
|
+
if (visibleA && visibleB) {
|
|
11968
|
+
tmpVec2b[0] += tmpVec2d[0];
|
|
11969
|
+
tmpVec2b[1] += tmpVec2d[1];
|
|
11970
|
+
math.mulVec2Scalar(tmpVec2b, .5);
|
|
11971
|
+
|
|
11972
|
+
tmpVec2b[0] += tmpVec2a[0] + tmpVec2c[0];
|
|
11973
|
+
tmpVec2b[1] += tmpVec2a[1] + tmpVec2c[1];
|
|
11974
|
+
math.mulVec2Scalar(tmpVec2b, 1/3);
|
|
11975
|
+
this._label.setPos(tmpVec2b[0], tmpVec2b[1]);
|
|
11976
|
+
} else if (visibleA) {
|
|
11977
|
+
setPosOnWire(tmpVec2a, tmpVec2b, 0);
|
|
11978
|
+
} else if (visibleB) {
|
|
11979
|
+
setPosOnWire(tmpVec2c, tmpVec2d, 0);
|
|
11939
11980
|
}
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
|
|
11950
|
-
|
|
11951
|
-
|
|
11952
|
-
|
|
11953
|
-
|
|
11954
|
-
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
&&
|
|
11961
|
-
(math.distVec2(tmpVec2a, tmpVec2b) >= this._labelMinAxisLength));
|
|
11962
|
-
this._label.setCulled(!visible);
|
|
11963
|
-
if (visible) {
|
|
11964
|
-
setPosOnWire(tmpVec2a, tmpVec2b, this._yOff);
|
|
11965
|
-
}
|
|
11981
|
+
};
|
|
11982
|
+
|
|
11983
|
+
this._updatePosOnWire = () => {
|
|
11984
|
+
const visible = (clipSegment(scene, parentElement, this._start, this._end, tmpVec2a, tmpVec2b)
|
|
11985
|
+
&&
|
|
11986
|
+
(math.distVec2(tmpVec2a, tmpVec2b) >= this._labelMinAxisLength));
|
|
11987
|
+
this._label.setCulled(!visible);
|
|
11988
|
+
if (visible) {
|
|
11989
|
+
setPosOnWire(tmpVec2a, tmpVec2b, this._yOff);
|
|
11990
|
+
}
|
|
11991
|
+
};
|
|
11992
|
+
|
|
11993
|
+
let posUpdate = () => { };
|
|
11994
|
+
this._setUpdatePositions = (_posUpdate) => {
|
|
11995
|
+
posUpdate = _posUpdate;
|
|
11996
|
+
this._updatePositions();
|
|
11997
|
+
};
|
|
11998
|
+
this._updatePositions = () => {
|
|
11999
|
+
if (this.__visible) {
|
|
12000
|
+
posUpdate();
|
|
11966
12001
|
}
|
|
11967
12002
|
};
|
|
11968
12003
|
|
|
@@ -11980,21 +12015,24 @@ class Label3D {
|
|
|
11980
12015
|
};
|
|
11981
12016
|
}
|
|
11982
12017
|
|
|
12018
|
+
setPos(p0) {
|
|
12019
|
+
this._start.set(p0);
|
|
12020
|
+
this._setUpdatePositions(this._updatePos);
|
|
12021
|
+
}
|
|
12022
|
+
|
|
11983
12023
|
setPosOnWire(p0, p1, yOff, labelMinAxisLength) {
|
|
11984
12024
|
this._start.set(p0);
|
|
11985
12025
|
this._end.set(p1);
|
|
11986
12026
|
this._yOff = yOff;
|
|
11987
12027
|
this._labelMinAxisLength = labelMinAxisLength;
|
|
11988
|
-
this.
|
|
11989
|
-
this._updatePositions();
|
|
12028
|
+
this._setUpdatePositions(this._updatePosOnWire);
|
|
11990
12029
|
}
|
|
11991
12030
|
|
|
11992
12031
|
setPosBetween(p0, p1, p2) {
|
|
11993
12032
|
this._start.set(p0);
|
|
11994
12033
|
this._mid.set(p1);
|
|
11995
12034
|
this._end.set(p2);
|
|
11996
|
-
this.
|
|
11997
|
-
this._updatePositions();
|
|
12035
|
+
this._setUpdatePositions(this._updatePosBetween);
|
|
11998
12036
|
}
|
|
11999
12037
|
|
|
12000
12038
|
setFillColor(value) {
|
|
@@ -12097,6 +12135,51 @@ class Wire3D {
|
|
|
12097
12135
|
|
|
12098
12136
|
}
|
|
12099
12137
|
|
|
12138
|
+
const marker3D = function(scene, color) {
|
|
12139
|
+
const marker = new Dot3D(scene, {}, scene.canvas.canvas.parentNode, {
|
|
12140
|
+
borderColor: "white",
|
|
12141
|
+
fillColor: color,
|
|
12142
|
+
zIndex: 100
|
|
12143
|
+
});
|
|
12144
|
+
|
|
12145
|
+
return {
|
|
12146
|
+
update: function(worldPos) {
|
|
12147
|
+
if (worldPos)
|
|
12148
|
+
{
|
|
12149
|
+
marker.worldPos = worldPos;
|
|
12150
|
+
}
|
|
12151
|
+
marker.setVisible(!!worldPos);
|
|
12152
|
+
},
|
|
12153
|
+
|
|
12154
|
+
setFillColor: c => marker.setFillColor(c),
|
|
12155
|
+
setHighlighted: h => marker.setHighlighted(h),
|
|
12156
|
+
getCanvasPos: () => marker.canvasPos,
|
|
12157
|
+
getWorldPos: () => marker.worldPos,
|
|
12158
|
+
destroy: () => marker.destroy()
|
|
12159
|
+
};
|
|
12160
|
+
};
|
|
12161
|
+
|
|
12162
|
+
const wire3D = function(scene, color) {
|
|
12163
|
+
const wire = new Wire3D(scene, scene.canvas.canvas.ownerDocument.body, {
|
|
12164
|
+
color: color,
|
|
12165
|
+
thickness: 1,
|
|
12166
|
+
thicknessClickable: 6 // TODO: Remove to make not clickable?
|
|
12167
|
+
});
|
|
12168
|
+
wire.setVisible(false);
|
|
12169
|
+
return {
|
|
12170
|
+
update: (startWorldPos, endWorldPos) => {
|
|
12171
|
+
if (endWorldPos)
|
|
12172
|
+
{
|
|
12173
|
+
wire.setEnds(startWorldPos, endWorldPos);
|
|
12174
|
+
}
|
|
12175
|
+
wire.setVisible(!!endWorldPos);
|
|
12176
|
+
},
|
|
12177
|
+
|
|
12178
|
+
setColor: c => wire.setColor(c),
|
|
12179
|
+
destroy: () => wire.destroy()
|
|
12180
|
+
};
|
|
12181
|
+
};
|
|
12182
|
+
|
|
12100
12183
|
function activateDraggableDot(dot, cfg) {
|
|
12101
12184
|
const extractCFG = function(propName, defaultValue) {
|
|
12102
12185
|
if (propName in cfg) {
|
|
@@ -12411,6 +12494,482 @@ const touchPointSelector = function(viewer, pointerCircle, ray2WorldPos) {
|
|
|
12411
12494
|
};
|
|
12412
12495
|
};
|
|
12413
12496
|
|
|
12497
|
+
const triangulateEarClipping = function(planeCoords) {
|
|
12498
|
+
const polygonVertices = [ ];
|
|
12499
|
+
for (let i = 0; i < planeCoords.length; ++i)
|
|
12500
|
+
polygonVertices.push(i);
|
|
12501
|
+
|
|
12502
|
+
const isCCW = (function() {
|
|
12503
|
+
const ba = math.vec2();
|
|
12504
|
+
const bc = math.vec2();
|
|
12505
|
+
|
|
12506
|
+
let anglesSum = 0;
|
|
12507
|
+
|
|
12508
|
+
for (let i = 0; i < polygonVertices.length; ++i)
|
|
12509
|
+
{
|
|
12510
|
+
const a = planeCoords[polygonVertices[i]];
|
|
12511
|
+
const b = planeCoords[polygonVertices[(i + 1) % polygonVertices.length]];
|
|
12512
|
+
const c = planeCoords[polygonVertices[(i + 2) % polygonVertices.length]];
|
|
12513
|
+
|
|
12514
|
+
math.subVec2(a, b, ba);
|
|
12515
|
+
math.subVec2(c, b, bc);
|
|
12516
|
+
|
|
12517
|
+
const theta = math.dotVec2(ba, bc) / Math.sqrt(math.sqLenVec2(ba) * math.sqLenVec2(bc));
|
|
12518
|
+
const angle = Math.acos(Math.max(-1, Math.min(theta, 1)));
|
|
12519
|
+
const convex = (ba[0] * bc[1] - ba[1] * bc[0]) >= 0;
|
|
12520
|
+
anglesSum += convex ? angle : (2 * Math.PI - angle);
|
|
12521
|
+
}
|
|
12522
|
+
|
|
12523
|
+
return anglesSum < (polygonVertices.length * Math.PI);
|
|
12524
|
+
})();
|
|
12525
|
+
|
|
12526
|
+
const pointInTriangle = (function() {
|
|
12527
|
+
const sign = (p1, p2, p3) => {
|
|
12528
|
+
return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]);
|
|
12529
|
+
};
|
|
12530
|
+
|
|
12531
|
+
return (pt, v1, v2, v3) => {
|
|
12532
|
+
const d1 = sign(pt, v1, v2);
|
|
12533
|
+
const d2 = sign(pt, v2, v3);
|
|
12534
|
+
const d3 = sign(pt, v3, v1);
|
|
12535
|
+
|
|
12536
|
+
const has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
|
|
12537
|
+
const has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
|
|
12538
|
+
|
|
12539
|
+
return !(has_neg && has_pos);
|
|
12540
|
+
};
|
|
12541
|
+
})();
|
|
12542
|
+
|
|
12543
|
+
const baseTriangles = [ ];
|
|
12544
|
+
|
|
12545
|
+
const vertices = (isCCW ? polygonVertices : polygonVertices.slice(0).reverse()).map(i => ({ idx: i }));
|
|
12546
|
+
vertices.forEach((v, i) => {
|
|
12547
|
+
v.prev = vertices[(i - 1 + vertices.length) % vertices.length];
|
|
12548
|
+
v.next = vertices[(i + 1) % vertices.length];
|
|
12549
|
+
});
|
|
12550
|
+
|
|
12551
|
+
const ba = math.vec2();
|
|
12552
|
+
const bc = math.vec2();
|
|
12553
|
+
|
|
12554
|
+
while (vertices.length > 2) {
|
|
12555
|
+
let earIdx = 0;
|
|
12556
|
+
while (true) {
|
|
12557
|
+
if (earIdx >= vertices.length)
|
|
12558
|
+
{
|
|
12559
|
+
throw `isCCW = ${isCCW}; earIdx = ${earIdx}; len = ${vertices.length}`;
|
|
12560
|
+
}
|
|
12561
|
+
const v = vertices[earIdx];
|
|
12562
|
+
|
|
12563
|
+
const a = planeCoords[v.prev.idx];
|
|
12564
|
+
const b = planeCoords[v.idx];
|
|
12565
|
+
const c = planeCoords[v.next.idx];
|
|
12566
|
+
|
|
12567
|
+
math.subVec2(a, b, ba);
|
|
12568
|
+
math.subVec2(c, b, bc);
|
|
12569
|
+
|
|
12570
|
+
if (((ba[0] * bc[1] - ba[1] * bc[0]) >= 0) // a convex vertex
|
|
12571
|
+
&&
|
|
12572
|
+
vertices.every( // no other vertices inside
|
|
12573
|
+
vv => ((vv === v)
|
|
12574
|
+
||
|
|
12575
|
+
(vv === v.prev)
|
|
12576
|
+
||
|
|
12577
|
+
(vv === v.next)
|
|
12578
|
+
||
|
|
12579
|
+
!pointInTriangle(planeCoords[vv.idx], a, b, c))))
|
|
12580
|
+
break;
|
|
12581
|
+
++earIdx;
|
|
12582
|
+
}
|
|
12583
|
+
|
|
12584
|
+
const ear = vertices[earIdx];
|
|
12585
|
+
vertices.splice(earIdx, 1);
|
|
12586
|
+
|
|
12587
|
+
baseTriangles.push([ ear.idx, ear.next.idx, ear.prev.idx ]);
|
|
12588
|
+
|
|
12589
|
+
const prev = ear.prev;
|
|
12590
|
+
prev.next = ear.next;
|
|
12591
|
+
const next = ear.next;
|
|
12592
|
+
next.prev = ear.prev;
|
|
12593
|
+
}
|
|
12594
|
+
|
|
12595
|
+
return [ planeCoords, baseTriangles, isCCW ];
|
|
12596
|
+
};
|
|
12597
|
+
|
|
12598
|
+
const addMousePressListener = function(element, onChange) {
|
|
12599
|
+
const moveTolerance = 4;
|
|
12600
|
+
|
|
12601
|
+
const copyElementPos = (event, out) => {
|
|
12602
|
+
out[0] = event.clientX;
|
|
12603
|
+
out[1] = event.clientY;
|
|
12604
|
+
transformToNode(element.ownerDocument.documentElement, element, out);
|
|
12605
|
+
return out;
|
|
12606
|
+
};
|
|
12607
|
+
|
|
12608
|
+
let buttonDown = false;
|
|
12609
|
+
|
|
12610
|
+
const cleanups = [ ];
|
|
12611
|
+
const cleanup = () => cleanups.forEach(c => c());
|
|
12612
|
+
|
|
12613
|
+
const addElementEventListener = (type, listener) => {
|
|
12614
|
+
element.addEventListener(type, listener);
|
|
12615
|
+
cleanups.push(() => element.removeEventListener(type, listener));
|
|
12616
|
+
};
|
|
12617
|
+
|
|
12618
|
+
const downPos = math.vec2();
|
|
12619
|
+
addElementEventListener("mousedown", function(event) {
|
|
12620
|
+
if (event.which === 1) {
|
|
12621
|
+
buttonDown = true;
|
|
12622
|
+
onChange(copyElementPos(event, downPos));
|
|
12623
|
+
}
|
|
12624
|
+
});
|
|
12625
|
+
|
|
12626
|
+
addElementEventListener("mousemove", function(event) {
|
|
12627
|
+
copyElementPos(event, tmpVec2a);
|
|
12628
|
+
if (buttonDown && (math.distVec2(downPos, tmpVec2a) > moveTolerance)) {
|
|
12629
|
+
buttonDown = false;
|
|
12630
|
+
}
|
|
12631
|
+
if (buttonDown || (! event.buttons & 1)) {
|
|
12632
|
+
onChange(tmpVec2a);
|
|
12633
|
+
}
|
|
12634
|
+
});
|
|
12635
|
+
|
|
12636
|
+
addElementEventListener("mouseup", function(event) {
|
|
12637
|
+
if ((event.which === 1) && buttonDown) {
|
|
12638
|
+
const commit = onChange(copyElementPos(event, tmpVec2a));
|
|
12639
|
+
if (commit) {
|
|
12640
|
+
cleanup();
|
|
12641
|
+
commit();
|
|
12642
|
+
}
|
|
12643
|
+
}
|
|
12644
|
+
});
|
|
12645
|
+
|
|
12646
|
+
return cleanup;
|
|
12647
|
+
};
|
|
12648
|
+
|
|
12649
|
+
const addTouchPressListener = function(element, cameraControl, pointerCircle, onChange) {
|
|
12650
|
+
const longTouchTimeoutMs = 300;
|
|
12651
|
+
const moveTolerance = 20;
|
|
12652
|
+
const startPos = math.vec2();
|
|
12653
|
+
|
|
12654
|
+
const copyElementPos = (event, out) => {
|
|
12655
|
+
out[0] = event.clientX;
|
|
12656
|
+
out[1] = event.clientY;
|
|
12657
|
+
transformToNode(element.ownerDocument.documentElement, element, out);
|
|
12658
|
+
return out;
|
|
12659
|
+
};
|
|
12660
|
+
|
|
12661
|
+
let longTouchTimeout = null;
|
|
12662
|
+
let onSingleTouchMove = nop;
|
|
12663
|
+
let startTouchIdentifier;
|
|
12664
|
+
|
|
12665
|
+
const resetAction = function() {
|
|
12666
|
+
clearTimeout(longTouchTimeout);
|
|
12667
|
+
pointerCircle.stop();
|
|
12668
|
+
cameraControl.active = true;
|
|
12669
|
+
onSingleTouchMove = nop;
|
|
12670
|
+
startTouchIdentifier = null;
|
|
12671
|
+
};
|
|
12672
|
+
|
|
12673
|
+
const cleanups = [ ];
|
|
12674
|
+
const cleanup = () => cleanups.forEach(c => c());
|
|
12675
|
+
|
|
12676
|
+
const addElementEventListener = (type, listener) => {
|
|
12677
|
+
element.addEventListener(type, listener, {passive: true});
|
|
12678
|
+
cleanups.push(() => element.removeEventListener(type, listener));
|
|
12679
|
+
};
|
|
12680
|
+
|
|
12681
|
+
addElementEventListener("touchstart", function(event) {
|
|
12682
|
+
const touches = event.touches;
|
|
12683
|
+
|
|
12684
|
+
if (touches.length !== 1)
|
|
12685
|
+
{
|
|
12686
|
+
resetAction();
|
|
12687
|
+
onChange(null);
|
|
12688
|
+
}
|
|
12689
|
+
else
|
|
12690
|
+
{
|
|
12691
|
+
const touch = touches[0];
|
|
12692
|
+
copyElementPos(touch, startPos);
|
|
12693
|
+
|
|
12694
|
+
startTouchIdentifier = touch.identifier;
|
|
12695
|
+
|
|
12696
|
+
onSingleTouchMove = elementPos => {
|
|
12697
|
+
if (math.distVec2(startPos, elementPos) > moveTolerance)
|
|
12698
|
+
{
|
|
12699
|
+
resetAction();
|
|
12700
|
+
}
|
|
12701
|
+
};
|
|
12702
|
+
|
|
12703
|
+
longTouchTimeout = setTimeout(
|
|
12704
|
+
function() {
|
|
12705
|
+
pointerCircle.start(startPos);
|
|
12706
|
+
|
|
12707
|
+
longTouchTimeout = setTimeout(
|
|
12708
|
+
function() {
|
|
12709
|
+
pointerCircle.stop();
|
|
12710
|
+
cameraControl.active = false;
|
|
12711
|
+
onSingleTouchMove = onChange;
|
|
12712
|
+
onSingleTouchMove(startPos);
|
|
12713
|
+
},
|
|
12714
|
+
longTouchTimeoutMs);
|
|
12715
|
+
},
|
|
12716
|
+
250);
|
|
12717
|
+
}
|
|
12718
|
+
});
|
|
12719
|
+
|
|
12720
|
+
// element.addEventListener("touchcancel", e => console.log("touchcancel", e), {passive: true});
|
|
12721
|
+
|
|
12722
|
+
addElementEventListener("touchmove", function(event) {
|
|
12723
|
+
const touch = [...event.changedTouches].find(e => e.identifier === startTouchIdentifier);
|
|
12724
|
+
if (touch)
|
|
12725
|
+
{
|
|
12726
|
+
onSingleTouchMove(copyElementPos(touch, tmpVec2a));
|
|
12727
|
+
}
|
|
12728
|
+
});
|
|
12729
|
+
|
|
12730
|
+
addElementEventListener("touchend", function(event) {
|
|
12731
|
+
const touch = [...event.changedTouches].find(e => e.identifier === startTouchIdentifier);
|
|
12732
|
+
if (touch)
|
|
12733
|
+
{
|
|
12734
|
+
const commit = onChange(copyElementPos(touch, tmpVec2a));
|
|
12735
|
+
resetAction();
|
|
12736
|
+
if (commit) {
|
|
12737
|
+
cleanup();
|
|
12738
|
+
commit();
|
|
12739
|
+
} else {
|
|
12740
|
+
onChange(null);
|
|
12741
|
+
}
|
|
12742
|
+
}
|
|
12743
|
+
});
|
|
12744
|
+
|
|
12745
|
+
return () => {
|
|
12746
|
+
resetAction();
|
|
12747
|
+
cleanup();
|
|
12748
|
+
};
|
|
12749
|
+
};
|
|
12750
|
+
|
|
12751
|
+
const startPolygonCreate = function(scene, pointerLens, addPressListener, pickRayResult, onChange, onConclude) {
|
|
12752
|
+
const canvas = scene.canvas.canvas;
|
|
12753
|
+
|
|
12754
|
+
const updatePointerLens = (pointerLens
|
|
12755
|
+
? function(canvasPos, isSnapped) {
|
|
12756
|
+
pointerLens.visible = !! canvasPos;
|
|
12757
|
+
if (canvasPos)
|
|
12758
|
+
{
|
|
12759
|
+
pointerLens.canvasPos = canvasPos;
|
|
12760
|
+
pointerLens.snapped = !! isSnapped;
|
|
12761
|
+
}
|
|
12762
|
+
}
|
|
12763
|
+
: () => { });
|
|
12764
|
+
|
|
12765
|
+
const testLastSegmentIntersects = (function() {
|
|
12766
|
+
const onSegment = (p, q, r) => ((q[0] <= Math.max(p[0], r[0])) &&
|
|
12767
|
+
(q[0] >= Math.min(p[0], r[0])) &&
|
|
12768
|
+
(q[1] <= Math.max(p[1], r[1])) &&
|
|
12769
|
+
(q[1] >= Math.min(p[1], r[1])));
|
|
12770
|
+
|
|
12771
|
+
const orient = (p, q, r) => {
|
|
12772
|
+
const val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);
|
|
12773
|
+
// collinear
|
|
12774
|
+
// clockwise
|
|
12775
|
+
// counterclockwise
|
|
12776
|
+
return ((val === 0) ? 0 : ((val > 0) ? 1 : 2));
|
|
12777
|
+
};
|
|
12778
|
+
|
|
12779
|
+
return function(pos2D, lastSegmentClosesLoop) {
|
|
12780
|
+
const s = lastSegmentClosesLoop ? 1 : 0;
|
|
12781
|
+
const a = pos2D[(pos2D.length - 2 + s) % pos2D.length];
|
|
12782
|
+
const b = pos2D[(pos2D.length - 1 + s) % pos2D.length];
|
|
12783
|
+
|
|
12784
|
+
for (let i = s; i < pos2D.length - 2 - 1 + s; ++i) {
|
|
12785
|
+
const c = pos2D[i];
|
|
12786
|
+
const d = pos2D[i + 1];
|
|
12787
|
+
|
|
12788
|
+
const o1 = orient(a, b, c);
|
|
12789
|
+
const o2 = orient(a, b, d);
|
|
12790
|
+
const o3 = orient(c, d, a);
|
|
12791
|
+
const o4 = orient(c, d, b);
|
|
12792
|
+
|
|
12793
|
+
if (((o1 !== o2) && (o3 !== o4)) || // General case
|
|
12794
|
+
((o1 === 0) && onSegment(a, c, b)) || // a, b and c are collinear and c lies on segment ab
|
|
12795
|
+
((o2 === 0) && onSegment(a, d, b)) || // a, b and d are collinear and d lies on segment ab
|
|
12796
|
+
((o3 === 0) && onSegment(c, a, d)) || // c, d and a are collinear and a lies on segment cd
|
|
12797
|
+
((o4 === 0) && onSegment(c, b, d))) // c, d and b are collinear and b lies on segment cd
|
|
12798
|
+
{
|
|
12799
|
+
return true;
|
|
12800
|
+
}
|
|
12801
|
+
}
|
|
12802
|
+
|
|
12803
|
+
return false;
|
|
12804
|
+
};
|
|
12805
|
+
})();
|
|
12806
|
+
|
|
12807
|
+
const getPlane = (points) => (points.length >= 3) && (function() {
|
|
12808
|
+
const u = math.normalizeVec3(math.subVec3(points[1], points[0], math.vec3()));
|
|
12809
|
+
const v20 = math.normalizeVec3(math.subVec3(points[2], points[0], tmpVec3a$2));
|
|
12810
|
+
const normal = math.normalizeVec3(math.cross3Vec3(u, v20, math.vec3()));
|
|
12811
|
+
const v = math.normalizeVec3(math.cross3Vec3(normal, u, math.vec3()));
|
|
12812
|
+
return {
|
|
12813
|
+
normal: normal,
|
|
12814
|
+
origin: math.vec3(points[0]),
|
|
12815
|
+
u: u,
|
|
12816
|
+
v: v
|
|
12817
|
+
};
|
|
12818
|
+
})();
|
|
12819
|
+
|
|
12820
|
+
const vertices = [ ];
|
|
12821
|
+
let currentInteraction;
|
|
12822
|
+
|
|
12823
|
+
(function selectNextPoint() {
|
|
12824
|
+
const plane = getPlane(vertices);
|
|
12825
|
+
|
|
12826
|
+
const canvasPos2Ray = (canvasPos, dst) => (math.canvasPosToWorldRay(canvas, scene.camera.viewMatrix, scene.camera.projMatrix, scene.camera.projection, canvasPos, dst.origin, dst.direction), dst);
|
|
12827
|
+
|
|
12828
|
+
const pickRay = (ray) => {
|
|
12829
|
+
const pickResult = pickRayResult(ray);
|
|
12830
|
+
const snapWorldPos = pickResult && pickResult.entity && ((! plane) || pickResult.snapped) && pickResult.worldPos;
|
|
12831
|
+
if (plane) {
|
|
12832
|
+
const originDistance = math.dotVec3(plane.normal, plane.origin);
|
|
12833
|
+
const snapPlaneDist = (snapWorldPos
|
|
12834
|
+
? ((originDistance - math.dotVec3(snapWorldPos, plane.normal)))
|
|
12835
|
+
: window.Infinity);
|
|
12836
|
+
if (Math.abs(snapPlaneDist) < 0.0001) {
|
|
12837
|
+
const ret = math.vec3();
|
|
12838
|
+
return {
|
|
12839
|
+
worldPos: math.addVec3(snapWorldPos, math.mulVec3Scalar(plane.normal, snapPlaneDist, ret), ret),
|
|
12840
|
+
snapped: true
|
|
12841
|
+
};
|
|
12842
|
+
} else {
|
|
12843
|
+
return {
|
|
12844
|
+
worldPos: planeIntersect$1(originDistance, plane.normal, ray.origin, ray.direction),
|
|
12845
|
+
snapped: false
|
|
12846
|
+
};
|
|
12847
|
+
}
|
|
12848
|
+
} else {
|
|
12849
|
+
return {
|
|
12850
|
+
worldPos: snapWorldPos,
|
|
12851
|
+
snapped: pickResult && pickResult.snapped
|
|
12852
|
+
};
|
|
12853
|
+
}
|
|
12854
|
+
};
|
|
12855
|
+
|
|
12856
|
+
let placeVertex = false;
|
|
12857
|
+
const removePressListener = addPressListener(
|
|
12858
|
+
(inputCanvasPos) => {
|
|
12859
|
+
const rayPick = inputCanvasPos && pickRay(canvasPos2Ray(inputCanvasPos, tmpRay));
|
|
12860
|
+
const worldPos = rayPick && rayPick.worldPos;
|
|
12861
|
+
return onWorldPos(worldPos, inputCanvasPos, rayPick && rayPick.snapped);
|
|
12862
|
+
});
|
|
12863
|
+
|
|
12864
|
+
const onWorldPos = (worldPos, inputCanvasPos, rayPickSnapped) => {
|
|
12865
|
+
const canvasPos = worldPos ? scene.camera.projectWorldPos(worldPos) : inputCanvasPos;
|
|
12866
|
+
const firstMarker = (vertices.length > 0) && (function() {
|
|
12867
|
+
const v = vertices[0];
|
|
12868
|
+
return {
|
|
12869
|
+
canvasPos: scene.camera.projectWorldPos(v),
|
|
12870
|
+
worldPos: v
|
|
12871
|
+
};
|
|
12872
|
+
})();
|
|
12873
|
+
const snapToFirst = (vertices.length >= 3) && ((canvasPos && (math.distVec2(canvasPos, firstMarker.canvasPos) < 10))
|
|
12874
|
+
||
|
|
12875
|
+
(worldPos && math.compareVec3(worldPos, firstMarker.worldPos)));
|
|
12876
|
+
|
|
12877
|
+
updatePointerLens(snapToFirst ? firstMarker.canvasPos : canvasPos, snapToFirst || rayPickSnapped);
|
|
12878
|
+
|
|
12879
|
+
const lastPointOverlaps = (inputCanvasPos
|
|
12880
|
+
&&
|
|
12881
|
+
((! worldPos)
|
|
12882
|
+
||
|
|
12883
|
+
((vertices.length < 3)
|
|
12884
|
+
? vertices.some(v => math.compareVec3(v, worldPos))
|
|
12885
|
+
: math.compareVec3(vertices[vertices.length - 1], worldPos))));
|
|
12886
|
+
|
|
12887
|
+
const points = vertices.concat(((! snapToFirst) && worldPos && (! lastPointOverlaps)) ? [worldPos] : []);
|
|
12888
|
+
|
|
12889
|
+
const curPlane = (! lastPointOverlaps) && (plane || getPlane(points));
|
|
12890
|
+
|
|
12891
|
+
const uvs = curPlane && points.map(p => {
|
|
12892
|
+
math.subVec3(p, curPlane.origin, tmpVec3a$2);
|
|
12893
|
+
return math.vec2([ math.dotVec3(tmpVec3a$2, curPlane.u), math.dotVec3(tmpVec3a$2, curPlane.v) ]);
|
|
12894
|
+
});
|
|
12895
|
+
|
|
12896
|
+
const isValid = (! lastPointOverlaps) && (! (uvs && testLastSegmentIntersects(uvs, snapToFirst)));
|
|
12897
|
+
const geometry = isValid && uvs && (snapToFirst || (! testLastSegmentIntersects(uvs, true))) && (function() {
|
|
12898
|
+
try {
|
|
12899
|
+
const [ baseVertices, baseTriangles, isCCW ] = triangulateEarClipping(uvs);
|
|
12900
|
+
return {
|
|
12901
|
+
faces: baseTriangles,
|
|
12902
|
+
vertices: baseVertices.map(uv => math.addVec3(
|
|
12903
|
+
curPlane.origin,
|
|
12904
|
+
math.addVec3(
|
|
12905
|
+
math.mulVec3Scalar(curPlane.u, uv[0], tmpVec3a$2),
|
|
12906
|
+
math.mulVec3Scalar(curPlane.v, uv[1], tmpVec3b$2),
|
|
12907
|
+
tmpVec3a$2),
|
|
12908
|
+
math.vec3()))
|
|
12909
|
+
};
|
|
12910
|
+
} catch (e) {
|
|
12911
|
+
console.warn("e", e);
|
|
12912
|
+
return false;
|
|
12913
|
+
}
|
|
12914
|
+
})();
|
|
12915
|
+
|
|
12916
|
+
onChange(points, snapToFirst, isValid, geometry);
|
|
12917
|
+
|
|
12918
|
+
return placeVertex = (isValid && (snapToFirst
|
|
12919
|
+
? () => {
|
|
12920
|
+
updatePointerLens(null);
|
|
12921
|
+
onConclude();
|
|
12922
|
+
}
|
|
12923
|
+
: () => {
|
|
12924
|
+
vertices.push(math.vec3(worldPos));
|
|
12925
|
+
updatePointerLens(null);
|
|
12926
|
+
selectNextPoint();
|
|
12927
|
+
}));
|
|
12928
|
+
};
|
|
12929
|
+
|
|
12930
|
+
currentInteraction = {
|
|
12931
|
+
closePolygon: (() => {
|
|
12932
|
+
const commit = (vertices.length >= 3) && onWorldPos(vertices[0]);
|
|
12933
|
+
if (commit) {
|
|
12934
|
+
removePressListener();
|
|
12935
|
+
commit();
|
|
12936
|
+
}
|
|
12937
|
+
return !! commit;
|
|
12938
|
+
}),
|
|
12939
|
+
placeVertex: () => {
|
|
12940
|
+
if (placeVertex) {
|
|
12941
|
+
removePressListener();
|
|
12942
|
+
placeVertex();
|
|
12943
|
+
}
|
|
12944
|
+
return !!placeVertex;
|
|
12945
|
+
},
|
|
12946
|
+
popVertex: () => {
|
|
12947
|
+
if (vertices.length > 0) {
|
|
12948
|
+
removePressListener();
|
|
12949
|
+
vertices.pop();
|
|
12950
|
+
selectNextPoint();
|
|
12951
|
+
return true;
|
|
12952
|
+
} else {
|
|
12953
|
+
return false;
|
|
12954
|
+
}
|
|
12955
|
+
},
|
|
12956
|
+
removePressListener: removePressListener,
|
|
12957
|
+
updateOnChange: () => onWorldPos()
|
|
12958
|
+
};
|
|
12959
|
+
})();
|
|
12960
|
+
|
|
12961
|
+
return {
|
|
12962
|
+
cancel: () => {
|
|
12963
|
+
currentInteraction.removePressListener();
|
|
12964
|
+
updatePointerLens(null);
|
|
12965
|
+
},
|
|
12966
|
+
closePolygon: () => currentInteraction.closePolygon(),
|
|
12967
|
+
placeVertex: () => currentInteraction.placeVertex(),
|
|
12968
|
+
popVertex: () => currentInteraction.popVertex(),
|
|
12969
|
+
updateOnChange: () => currentInteraction.updateOnChange()
|
|
12970
|
+
};
|
|
12971
|
+
};
|
|
12972
|
+
|
|
12414
12973
|
const tmpVec3a$1 = math.vec3();
|
|
12415
12974
|
const tmpVec3b$1 = math.vec3();
|
|
12416
12975
|
|
|
@@ -14830,6 +15389,8 @@ const tempVec3a$M = math.vec3();
|
|
|
14830
15389
|
const tempVec3b$B = math.vec3();
|
|
14831
15390
|
const tempVec3c$w = math.vec3();
|
|
14832
15391
|
|
|
15392
|
+
const px = x => x + "px";
|
|
15393
|
+
|
|
14833
15394
|
/**
|
|
14834
15395
|
* A {@link Marker} with an HTML label attached to it, managed by an {@link AnnotationsPlugin}.
|
|
14835
15396
|
*
|
|
@@ -15036,22 +15597,29 @@ class Annotation extends Marker {
|
|
|
15036
15597
|
* @private
|
|
15037
15598
|
*/
|
|
15038
15599
|
_updateWithCurWidths() {
|
|
15039
|
-
const px = x => x + "px";
|
|
15040
15600
|
const boundary = this.scene.canvas.boundary;
|
|
15041
15601
|
const left = boundary[0] + this.canvasPos[0];
|
|
15042
15602
|
const top = boundary[1] + this.canvasPos[1];
|
|
15043
|
-
|
|
15044
|
-
const markerDir = (this._markerAlign === "right") ? -1 : ((this._markerAlign === "center") ? 0 : 1);
|
|
15045
|
-
const markerCenter = left + markerDir * (markerWidth / 2 - 12);
|
|
15046
|
-
this._marker.style.left = px(markerCenter - markerWidth / 2);
|
|
15047
|
-
this._marker.style.top = px(top - 12);
|
|
15048
|
-
this._marker.style["z-index"] = 90005 + Math.floor(this._viewPos[2]) + 1;
|
|
15049
|
-
|
|
15050
|
-
const labelWidth = this._curLabelWidth;
|
|
15051
|
-
const labelDir = Math.sign(this._labelPosition);
|
|
15052
|
-
this._label.style.left = px(markerCenter + labelDir * (markerWidth / 2 + Math.abs(this._labelPosition) + labelWidth / 2) - labelWidth / 2);
|
|
15603
|
+
this._marker.style.top = px(top - 12);
|
|
15053
15604
|
this._label.style.top = px(top - 17);
|
|
15054
|
-
|
|
15605
|
+
|
|
15606
|
+
if (this._markerAlign === "legacy") {
|
|
15607
|
+
this._marker.style.left = px(left - 12);
|
|
15608
|
+
this._label.style.left = px(left + 40);
|
|
15609
|
+
} else {
|
|
15610
|
+
const markerWidth = this._curMarkerWidth;
|
|
15611
|
+
const markerDir = (this._markerAlign === "right") ? -1 : ((this._markerAlign === "center") ? 0 : 1);
|
|
15612
|
+
const markerCenter = left + markerDir * (markerWidth / 2 - 12);
|
|
15613
|
+
this._marker.style.left = px(markerCenter - markerWidth / 2);
|
|
15614
|
+
|
|
15615
|
+
const labelWidth = this._curLabelWidth;
|
|
15616
|
+
const labelDir = Math.sign(this._labelPosition);
|
|
15617
|
+
this._label.style.left = px(markerCenter + labelDir * (markerWidth / 2 + Math.abs(this._labelPosition) + labelWidth / 2) - labelWidth / 2);
|
|
15618
|
+
}
|
|
15619
|
+
|
|
15620
|
+
const zIndex = 90005 + Math.floor(this._viewPos[2]) + 1;
|
|
15621
|
+
this._marker.style["z-index"] = zIndex;
|
|
15622
|
+
this._label.style["z-index"] = zIndex;
|
|
15055
15623
|
}
|
|
15056
15624
|
|
|
15057
15625
|
/**
|
|
@@ -15082,7 +15650,8 @@ class Annotation extends Marker {
|
|
|
15082
15650
|
* @private
|
|
15083
15651
|
*/
|
|
15084
15652
|
_updatePosition() {
|
|
15085
|
-
|
|
15653
|
+
const isLegacy = this._markerAlign === "legacy";
|
|
15654
|
+
if ((! isLegacy) && (this._curMarkerWidth === undefined)) {
|
|
15086
15655
|
this._updateIfWidthsChanged();
|
|
15087
15656
|
} else {
|
|
15088
15657
|
// Update position with cached width values
|
|
@@ -15090,7 +15659,9 @@ class Annotation extends Marker {
|
|
|
15090
15659
|
// so they don't interfere with e.g. interactive scene manipulation
|
|
15091
15660
|
this._updateWithCurWidths();
|
|
15092
15661
|
window.clearTimeout(this._widthTimeout);
|
|
15093
|
-
|
|
15662
|
+
if (! isLegacy) {
|
|
15663
|
+
this._widthTimeout = window.setTimeout(() => this._updateIfWidthsChanged(), 500);
|
|
15664
|
+
}
|
|
15094
15665
|
}
|
|
15095
15666
|
}
|
|
15096
15667
|
|
|
@@ -15128,10 +15699,10 @@ class Annotation extends Marker {
|
|
|
15128
15699
|
/**
|
|
15129
15700
|
* Sets the horizontal alignment of the Annotation's marker HTML.
|
|
15130
15701
|
*
|
|
15131
|
-
* @param {String} align Either "left", "center", "right" (default "left")
|
|
15702
|
+
* @param {String} align Either "left", "center", "right", "legacy" (default "left")
|
|
15132
15703
|
*/
|
|
15133
15704
|
setMarkerAlign(align) {
|
|
15134
|
-
const valid = [ "left", "center", "right" ];
|
|
15705
|
+
const valid = [ "left", "center", "right", "legacy" ];
|
|
15135
15706
|
if (! valid.includes(align)) {
|
|
15136
15707
|
this.error("Param 'align' should be one of: " + JSON.stringify(valid));
|
|
15137
15708
|
} else {
|
|
@@ -26514,6 +27085,65 @@ class ReadableGeometry extends Geometry {
|
|
|
26514
27085
|
return this._obb;
|
|
26515
27086
|
}
|
|
26516
27087
|
|
|
27088
|
+
_getMetrics() {
|
|
27089
|
+
if (! ("_metrics" in this)) {
|
|
27090
|
+
switch (this._state.primitiveName) {
|
|
27091
|
+
case "solid":
|
|
27092
|
+
case "surface":
|
|
27093
|
+
case "triangles": {
|
|
27094
|
+
const indices = this._state.indices;
|
|
27095
|
+
const positions = this._state.positions;
|
|
27096
|
+
const getPos = (i, out) => {
|
|
27097
|
+
const idx = indices[i] * 3;
|
|
27098
|
+
for (let j = 0; j < 3; ++j) {
|
|
27099
|
+
out[j] = positions[idx + j];
|
|
27100
|
+
} return out;
|
|
27101
|
+
};
|
|
27102
|
+
const tmp = [ math.vec3(), math.vec3(), math.vec3(), math.vec3() ];
|
|
27103
|
+
let totalArea = 0;
|
|
27104
|
+
const centroid = math.vec3([ 0, 0, 0 ]);
|
|
27105
|
+
for (let i = 0; i < indices.length; i += 3) {
|
|
27106
|
+
const v0 = getPos(i, tmp[0]);
|
|
27107
|
+
const v1 = getPos(i+1, tmp[1]);
|
|
27108
|
+
const v2 = getPos(i+2, tmp[2]);
|
|
27109
|
+
math.addVec3(v0, v1, tmp[3]);
|
|
27110
|
+
math.addVec3(v2, tmp[3], tmp[3]);
|
|
27111
|
+
const faceArea = math.lenVec3(
|
|
27112
|
+
math.cross3Vec3(
|
|
27113
|
+
math.subVec3(v1, v0, tmp[1]),
|
|
27114
|
+
math.subVec3(v2, v0, tmp[2]),
|
|
27115
|
+
tmp[0])) / 2;
|
|
27116
|
+
totalArea += faceArea;
|
|
27117
|
+
math.mulVec3Scalar(tmp[3], faceArea, tmp[3]);
|
|
27118
|
+
math.addVec3(centroid, tmp[3], centroid);
|
|
27119
|
+
}
|
|
27120
|
+
this._metrics = { surfaceArea: totalArea, centroid: math.mulVec3Scalar(centroid, 1 / totalArea / 3, centroid) };
|
|
27121
|
+
break;
|
|
27122
|
+
}
|
|
27123
|
+
default:
|
|
27124
|
+
this._metrics = { surfaceArea: 0 };
|
|
27125
|
+
break;
|
|
27126
|
+
}
|
|
27127
|
+
}
|
|
27128
|
+
return this._metrics;
|
|
27129
|
+
}
|
|
27130
|
+
|
|
27131
|
+
/**
|
|
27132
|
+
* Returns the surface area of this Mesh.
|
|
27133
|
+
* @returns {number}
|
|
27134
|
+
*/
|
|
27135
|
+
get surfaceArea() {
|
|
27136
|
+
return this._getMetrics().surfaceArea;
|
|
27137
|
+
}
|
|
27138
|
+
|
|
27139
|
+
/**
|
|
27140
|
+
* Returns the centroid of this Mesh.
|
|
27141
|
+
* @returns {number}
|
|
27142
|
+
*/
|
|
27143
|
+
get centroid() {
|
|
27144
|
+
return this._getMetrics().centroid;
|
|
27145
|
+
}
|
|
27146
|
+
|
|
26517
27147
|
/**
|
|
26518
27148
|
* Approximate number of triangles in this ReadableGeometry.
|
|
26519
27149
|
*
|
|
@@ -40062,7 +40692,7 @@ function buildPlaneGeometry(cfg = {}) {
|
|
|
40062
40692
|
positions[offset + 1] = centerY;
|
|
40063
40693
|
positions[offset + 2] = -z + centerZ;
|
|
40064
40694
|
|
|
40065
|
-
normals[offset +
|
|
40695
|
+
normals[offset + 1] = 1;
|
|
40066
40696
|
|
|
40067
40697
|
uvs[offset2] = (ix) / planeX;
|
|
40068
40698
|
uvs[offset2 + 1] = ((planeZ - iz) / planeZ);
|
|
@@ -43360,8 +43990,7 @@ class SectionCaps {
|
|
|
43360
43990
|
if(!this._resourcesAllocated) {
|
|
43361
43991
|
this._resourcesAllocated = true;
|
|
43362
43992
|
this._sectionPlanes = [];
|
|
43363
|
-
this.
|
|
43364
|
-
this._indicesMap = {};
|
|
43993
|
+
this._sceneModelsData = {};
|
|
43365
43994
|
this._dirtyMap = {};
|
|
43366
43995
|
this._prevIntersectionModelsMap = {};
|
|
43367
43996
|
this._sectionPlaneTimeout = null;
|
|
@@ -43376,7 +44005,8 @@ class SectionCaps {
|
|
|
43376
44005
|
this._sectionPlanes.push(sectionPlane);
|
|
43377
44006
|
sectionPlane.on('pos', onSectionPlaneUpdated);
|
|
43378
44007
|
sectionPlane.on('dir', onSectionPlaneUpdated);
|
|
43379
|
-
sectionPlane.
|
|
44008
|
+
sectionPlane.on('active', onSectionPlaneUpdated);
|
|
44009
|
+
sectionPlane.once('destroyed', (() => {
|
|
43380
44010
|
const sectionPlaneId = sectionPlane.id;
|
|
43381
44011
|
if (sectionPlaneId) {
|
|
43382
44012
|
this._sectionPlanes = this._sectionPlanes.filter((sectionPlane) => sectionPlane.id !== sectionPlaneId);
|
|
@@ -43393,13 +44023,19 @@ class SectionCaps {
|
|
|
43393
44023
|
|
|
43394
44024
|
this._onTick = this.scene.on("tick", () => {
|
|
43395
44025
|
//on ticks we only check if there is a model that we have saved vertices for,
|
|
43396
|
-
//but it's no more available on the scene
|
|
43397
|
-
|
|
43398
|
-
|
|
43399
|
-
|
|
43400
|
-
delete this.
|
|
43401
|
-
|
|
43402
|
-
}
|
|
44026
|
+
//but it's no more available on the scene, or if its visibility changed
|
|
44027
|
+
let dirty = false;
|
|
44028
|
+
for(const sceneModelId in this._sceneModelsData) {
|
|
44029
|
+
if(!this.scene.models[sceneModelId]){
|
|
44030
|
+
delete this._sceneModelsData[sceneModelId];
|
|
44031
|
+
dirty = true;
|
|
44032
|
+
} else if (this._sceneModelsData[sceneModelId].visible !== (!!this.scene.models[sceneModelId].visible)) {
|
|
44033
|
+
this._sceneModelsData[sceneModelId].visible = !!this.scene.models[sceneModelId].visible;
|
|
44034
|
+
dirty = true;
|
|
44035
|
+
}
|
|
44036
|
+
}
|
|
44037
|
+
if (dirty) {
|
|
44038
|
+
this._update();
|
|
43403
44039
|
}
|
|
43404
44040
|
});
|
|
43405
44041
|
}
|
|
@@ -43416,8 +44052,8 @@ class SectionCaps {
|
|
|
43416
44052
|
this._deletePreviousModels();
|
|
43417
44053
|
this._updateTimeout = setTimeout(() => {
|
|
43418
44054
|
clearTimeout(this._updateTimeout);
|
|
43419
|
-
const sceneModels = Object.
|
|
43420
|
-
this._addHatches(sceneModels, this._sectionPlanes);
|
|
44055
|
+
const sceneModels = Object.values(this.scene.models).filter(sceneModel => sceneModel.visible);
|
|
44056
|
+
this._addHatches(sceneModels, this._sectionPlanes.filter(sectionPlane => sectionPlane.active));
|
|
43421
44057
|
this._setAllDirty(false);
|
|
43422
44058
|
}, 100);
|
|
43423
44059
|
}
|
|
@@ -43430,21 +44066,9 @@ class SectionCaps {
|
|
|
43430
44066
|
|
|
43431
44067
|
_addHatches(sceneModels, planes) {
|
|
43432
44068
|
|
|
43433
|
-
if (planes.length <= 0) return;
|
|
43434
|
-
|
|
43435
44069
|
planes.forEach((plane) => {
|
|
43436
44070
|
sceneModels.forEach((sceneModel) => {
|
|
43437
|
-
|
|
43438
|
-
//we create a plane equation that will be used to slice through each triangle
|
|
43439
|
-
const planeEquation = {
|
|
43440
|
-
A: plane.dir[0],
|
|
43441
|
-
B: plane.dir[1],
|
|
43442
|
-
C: plane.dir[2],
|
|
43443
|
-
D: -(plane.dir[0] * plane.pos[0] + plane.dir[1] * plane.pos[1] + plane.dir[2] * plane.pos[2])
|
|
43444
|
-
};
|
|
43445
|
-
//#endregion
|
|
43446
|
-
|
|
43447
|
-
if(!this._doesPlaneIntersectBoundingBox(sceneModel.aabb, planeEquation)) return;
|
|
44071
|
+
if(!this._doesPlaneIntersectBoundingBox(sceneModel.aabb, plane)) return;
|
|
43448
44072
|
|
|
43449
44073
|
if(!this._dirtyMap[sceneModel.id]) return;
|
|
43450
44074
|
|
|
@@ -43466,39 +44090,35 @@ class SectionCaps {
|
|
|
43466
44090
|
|
|
43467
44091
|
const object = objects[objectId];
|
|
43468
44092
|
|
|
43469
|
-
if(!this._doesPlaneIntersectBoundingBox(object.aabb,
|
|
44093
|
+
if(!this._doesPlaneIntersectBoundingBox(object.aabb, plane)) return;
|
|
43470
44094
|
|
|
43471
|
-
if(!this.
|
|
43472
|
-
this.
|
|
43473
|
-
|
|
44095
|
+
if(!this._sceneModelsData[sceneModel.id]) {
|
|
44096
|
+
this._sceneModelsData[sceneModel.id] = {
|
|
44097
|
+
verticesMap: new Map(),
|
|
44098
|
+
indicesMap: new Map()
|
|
44099
|
+
};
|
|
43474
44100
|
}
|
|
43475
44101
|
|
|
43476
|
-
|
|
44102
|
+
const sceneModelData = this._sceneModelsData[sceneModel.id];
|
|
43477
44103
|
|
|
43478
|
-
if(!
|
|
44104
|
+
if(!sceneModelData.verticesMap.has(objectId)) {
|
|
43479
44105
|
const isSolid = object.meshes[0].isSolid();
|
|
44106
|
+
const vertices = [ ];
|
|
44107
|
+
const indices = [ ];
|
|
43480
44108
|
if(isSolid && object.capMaterial) {
|
|
43481
|
-
object.getEachVertex(
|
|
43482
|
-
|
|
43483
|
-
});
|
|
43484
|
-
object.getEachIndex((_indices) => {
|
|
43485
|
-
indices.push(_indices);
|
|
43486
|
-
});
|
|
44109
|
+
object.getEachVertex(v => vertices.push(v[0], v[1], v[2]));
|
|
44110
|
+
object.getEachIndex(i => indices.push(i));
|
|
43487
44111
|
}
|
|
43488
|
-
|
|
43489
|
-
|
|
44112
|
+
sceneModelData.verticesMap.set(objectId, vertices);
|
|
44113
|
+
sceneModelData.indicesMap.set(objectId, indices);
|
|
43490
44114
|
}
|
|
43491
|
-
|
|
43492
|
-
|
|
43493
|
-
|
|
43494
|
-
|
|
43495
|
-
|
|
44115
|
+
|
|
44116
|
+
const vertices = sceneModelData.verticesMap.get(objectId);
|
|
44117
|
+
const indices = sceneModelData.indicesMap.get(objectId);
|
|
44118
|
+
|
|
43496
44119
|
const capSegments = [];
|
|
43497
44120
|
const vertCount = indices.length;
|
|
43498
|
-
|
|
43499
|
-
// Preallocate intersection result array
|
|
43500
|
-
const intersectionBuffer = new Float32Array(3);
|
|
43501
|
-
|
|
44121
|
+
|
|
43502
44122
|
for (let i = 0; i < vertCount; i += 3) {
|
|
43503
44123
|
// Reuse triangle buffer instead of creating new arrays
|
|
43504
44124
|
for (let j = 0; j < 3; j++) {
|
|
@@ -43515,21 +44135,15 @@ class SectionCaps {
|
|
|
43515
44135
|
for (let i = 0; i < 3; i++) {
|
|
43516
44136
|
const p1 = triangle[i];
|
|
43517
44137
|
const p2 = triangle[(i + 1) % 3];
|
|
43518
|
-
|
|
43519
|
-
|
|
43520
|
-
const
|
|
43521
|
-
|
|
43522
|
-
|
|
44138
|
+
|
|
44139
|
+
const d1 = plane.dist + math.dotVec3(plane.dir, p1);
|
|
44140
|
+
const d2 = plane.dist + math.dotVec3(plane.dir, p2);
|
|
44141
|
+
|
|
43523
44142
|
if (d1 * d2 > 0) continue;
|
|
43524
|
-
|
|
44143
|
+
|
|
43525
44144
|
const t = -d1 / (d2 - d1);
|
|
43526
|
-
|
|
43527
|
-
|
|
43528
|
-
intersectionBuffer[1] = p1[1] + t * (p2[1] - p1[1]);
|
|
43529
|
-
intersectionBuffer[2] = p1[2] + t * (p2[2] - p1[2]);
|
|
43530
|
-
|
|
43531
|
-
// Clone the buffer for storage
|
|
43532
|
-
intersections.push(new Float32Array(intersectionBuffer));
|
|
44145
|
+
|
|
44146
|
+
intersections.push(math.lerpVec3(t, 0, 1, p1, p2, math.vec3()));
|
|
43533
44147
|
}
|
|
43534
44148
|
|
|
43535
44149
|
if(intersections.length === 2) capSegments.push(intersections);
|
|
@@ -43809,7 +44423,7 @@ class SectionCaps {
|
|
|
43809
44423
|
|
|
43810
44424
|
}
|
|
43811
44425
|
|
|
43812
|
-
_doesPlaneIntersectBoundingBox(bb,
|
|
44426
|
+
_doesPlaneIntersectBoundingBox(bb, plane) {
|
|
43813
44427
|
const min = [bb[0], bb[1], bb[2]];
|
|
43814
44428
|
const max = [bb[3], bb[4], bb[5]];
|
|
43815
44429
|
|
|
@@ -43829,10 +44443,7 @@ class SectionCaps {
|
|
|
43829
44443
|
let hasNegative = false;
|
|
43830
44444
|
|
|
43831
44445
|
for (const corner of corners) {
|
|
43832
|
-
const distance =
|
|
43833
|
-
planeEquation.B * corner[1] +
|
|
43834
|
-
planeEquation.C * corner[2] +
|
|
43835
|
-
planeEquation.D;
|
|
44446
|
+
const distance = plane.dist + math.dotVec3(plane.dir, corner);
|
|
43836
44447
|
|
|
43837
44448
|
if (distance > 0) hasPositive = true;
|
|
43838
44449
|
if (distance < 0) hasNegative = true;
|
|
@@ -44327,13 +44938,12 @@ class Scene extends Component {
|
|
|
44327
44938
|
* configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing
|
|
44328
44939
|
* 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
|
|
44329
44940
|
* your expected usage.
|
|
44330
|
-
* @throws {String} Throws an exception when
|
|
44941
|
+
* @throws {String} Throws an exception when canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.
|
|
44331
44942
|
*/
|
|
44332
44943
|
constructor(viewer, cfg = {}) {
|
|
44333
44944
|
|
|
44334
44945
|
super(null, cfg);
|
|
44335
|
-
|
|
44336
|
-
const canvas = cfg.canvasElement || document.getElementById(cfg.canvasId);
|
|
44946
|
+
const canvas = cfg.canvasElement || document.querySelector(`#${cfg.canvasId}`);
|
|
44337
44947
|
|
|
44338
44948
|
if (!(canvas instanceof HTMLCanvasElement)) {
|
|
44339
44949
|
throw "Mandatory config expected: valid canvasId or canvasElement";
|
|
@@ -123581,6 +124191,7 @@ function CubeTextureCanvas(viewer, navCubeScene, cfg = {}) {
|
|
|
123581
124191
|
const cubeColor = "lightgrey";
|
|
123582
124192
|
const cubeHighlightColor = cfg.hoverColor || "rgba(0,0,0,0.4)";
|
|
123583
124193
|
const textColor = cfg.textColor || "black";
|
|
124194
|
+
const parentNode = cfg.canvasElement || document.body;
|
|
123584
124195
|
|
|
123585
124196
|
const height = 500;
|
|
123586
124197
|
const width = height + (height / 3);
|
|
@@ -123690,8 +124301,7 @@ function CubeTextureCanvas(viewer, navCubeScene, cfg = {}) {
|
|
|
123690
124301
|
this._textureCanvas.style.visibility = "hidden";
|
|
123691
124302
|
this._textureCanvas.style["z-index"] = 2000000;
|
|
123692
124303
|
|
|
123693
|
-
|
|
123694
|
-
body.appendChild(this._textureCanvas);
|
|
124304
|
+
parentNode.appendChild(this._textureCanvas);
|
|
123695
124305
|
|
|
123696
124306
|
const context = this._textureCanvas.getContext("2d");
|
|
123697
124307
|
|
|
@@ -123961,7 +124571,7 @@ class NavCubePlugin extends Plugin {
|
|
|
123961
124571
|
this._navCubeScene = new Scene(viewer, {
|
|
123962
124572
|
canvasId: cfg.canvasId,
|
|
123963
124573
|
canvasElement: cfg.canvasElement,
|
|
123964
|
-
transparent: true
|
|
124574
|
+
transparent: true,
|
|
123965
124575
|
});
|
|
123966
124576
|
|
|
123967
124577
|
this._navCubeCanvas = this._navCubeScene.canvas.canvas;
|
|
@@ -124194,7 +124804,7 @@ class NavCubePlugin extends Plugin {
|
|
|
124194
124804
|
}
|
|
124195
124805
|
});
|
|
124196
124806
|
|
|
124197
|
-
|
|
124807
|
+
self._navCubeCanvas.addEventListener("mouseup", self._onMouseUp = function (e) {
|
|
124198
124808
|
if (e.which !== 1) {// Left button
|
|
124199
124809
|
return;
|
|
124200
124810
|
}
|
|
@@ -124211,7 +124821,7 @@ class NavCubePlugin extends Plugin {
|
|
|
124211
124821
|
if (hit.uv) {
|
|
124212
124822
|
var areaId = self._cubeTextureCanvas.getArea(hit.uv);
|
|
124213
124823
|
if (areaId >= 0) {
|
|
124214
|
-
|
|
124824
|
+
self._navCubeCanvas.style.cursor = "pointer";
|
|
124215
124825
|
if (lastAreaId >= 0) {
|
|
124216
124826
|
self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
|
|
124217
124827
|
self._repaint();
|
|
@@ -124237,7 +124847,7 @@ class NavCubePlugin extends Plugin {
|
|
|
124237
124847
|
self._repaint();
|
|
124238
124848
|
lastAreaId = -1;
|
|
124239
124849
|
}
|
|
124240
|
-
|
|
124850
|
+
self._navCubeCanvas.style.cursor = "pointer";
|
|
124241
124851
|
if (lastAreaId >= 0) {
|
|
124242
124852
|
self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
|
|
124243
124853
|
self._repaint();
|
|
@@ -124256,7 +124866,7 @@ class NavCubePlugin extends Plugin {
|
|
|
124256
124866
|
}
|
|
124257
124867
|
});
|
|
124258
124868
|
|
|
124259
|
-
|
|
124869
|
+
self._navCubeCanvas.addEventListener("mousemove", self._onMouseMove = function (e) {
|
|
124260
124870
|
if (lastAreaId >= 0) {
|
|
124261
124871
|
self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
|
|
124262
124872
|
self._repaint();
|
|
@@ -124268,7 +124878,7 @@ class NavCubePlugin extends Plugin {
|
|
|
124268
124878
|
if (down) {
|
|
124269
124879
|
var posX = e.clientX;
|
|
124270
124880
|
var posY = e.clientY;
|
|
124271
|
-
|
|
124881
|
+
self._navCubeCanvas.style.cursor = "move";
|
|
124272
124882
|
actionMove(posX, posY);
|
|
124273
124883
|
return;
|
|
124274
124884
|
}
|
|
@@ -124282,7 +124892,7 @@ class NavCubePlugin extends Plugin {
|
|
|
124282
124892
|
});
|
|
124283
124893
|
if (hit) {
|
|
124284
124894
|
if (hit.uv) {
|
|
124285
|
-
|
|
124895
|
+
self._navCubeCanvas.style.cursor = "pointer";
|
|
124286
124896
|
var areaId = self._cubeTextureCanvas.getArea(hit.uv);
|
|
124287
124897
|
if (areaId === lastAreaId) {
|
|
124288
124898
|
return;
|
|
@@ -124297,7 +124907,7 @@ class NavCubePlugin extends Plugin {
|
|
|
124297
124907
|
}
|
|
124298
124908
|
}
|
|
124299
124909
|
} else {
|
|
124300
|
-
|
|
124910
|
+
self._navCubeCanvas.style.cursor = "default";
|
|
124301
124911
|
if (lastAreaId >= 0) {
|
|
124302
124912
|
self._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);
|
|
124303
124913
|
self._repaint();
|
|
@@ -124560,8 +125170,8 @@ class NavCubePlugin extends Plugin {
|
|
|
124560
125170
|
this._navCubeCanvas.removeEventListener("mouseleave", this._onMouseLeave);
|
|
124561
125171
|
this._navCubeCanvas.removeEventListener("mousedown", this._onMouseDown);
|
|
124562
125172
|
|
|
124563
|
-
|
|
124564
|
-
|
|
125173
|
+
this._navCubeCanvas.removeEventListener("mousemove", this._onMouseMove);
|
|
125174
|
+
this._navCubeCanvas.removeEventListener("mouseup", this._onMouseUp);
|
|
124565
125175
|
|
|
124566
125176
|
this._navCubeCanvas = null;
|
|
124567
125177
|
this._cubeTextureCanvas.destroy();
|
|
@@ -125955,8 +126565,8 @@ class Control {
|
|
|
125955
126565
|
const canvasPos = math.vec2();
|
|
125956
126566
|
|
|
125957
126567
|
const copyCanvasPos = (event, vec2) => {
|
|
125958
|
-
vec2[0] = event.
|
|
125959
|
-
vec2[1] = event.
|
|
126568
|
+
vec2[0] = event.pageX;
|
|
126569
|
+
vec2[1] = event.pageY;
|
|
125960
126570
|
transformToNode(canvas.ownerDocument.documentElement, canvas, vec2);
|
|
125961
126571
|
};
|
|
125962
126572
|
|
|
@@ -168436,151 +169046,6 @@ const hex2rgb = function(color) {
|
|
|
168436
169046
|
return [ rgb(0), rgb(2), rgb(4) ];
|
|
168437
169047
|
};
|
|
168438
169048
|
|
|
168439
|
-
const triangulateEarClipping = function(planeCoords) {
|
|
168440
|
-
|
|
168441
|
-
const polygonVertices = [ ];
|
|
168442
|
-
for (let i = 0; i < planeCoords.length; ++i)
|
|
168443
|
-
polygonVertices.push(i);
|
|
168444
|
-
|
|
168445
|
-
const isCCW = (function() {
|
|
168446
|
-
const ba = math.vec2();
|
|
168447
|
-
const bc = math.vec2();
|
|
168448
|
-
|
|
168449
|
-
let anglesSum = 0;
|
|
168450
|
-
|
|
168451
|
-
for (let i = 0; i < polygonVertices.length; ++i)
|
|
168452
|
-
{
|
|
168453
|
-
const a = planeCoords[polygonVertices[i]];
|
|
168454
|
-
const b = planeCoords[polygonVertices[(i + 1) % polygonVertices.length]];
|
|
168455
|
-
const c = planeCoords[polygonVertices[(i + 2) % polygonVertices.length]];
|
|
168456
|
-
|
|
168457
|
-
math.subVec2(a, b, ba);
|
|
168458
|
-
math.subVec2(c, b, bc);
|
|
168459
|
-
|
|
168460
|
-
const theta = math.dotVec2(ba, bc) / Math.sqrt(math.sqLenVec2(ba) * math.sqLenVec2(bc));
|
|
168461
|
-
const angle = Math.acos(Math.max(-1, Math.min(theta, 1)));
|
|
168462
|
-
const convex = (ba[0] * bc[1] - ba[1] * bc[0]) >= 0;
|
|
168463
|
-
anglesSum += convex ? angle : (2 * Math.PI - angle);
|
|
168464
|
-
}
|
|
168465
|
-
|
|
168466
|
-
return anglesSum < (polygonVertices.length * Math.PI);
|
|
168467
|
-
})();
|
|
168468
|
-
|
|
168469
|
-
const pointInTriangle = (function() {
|
|
168470
|
-
const sign = (p1, p2, p3) => {
|
|
168471
|
-
return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]);
|
|
168472
|
-
};
|
|
168473
|
-
|
|
168474
|
-
return (pt, v1, v2, v3) => {
|
|
168475
|
-
const d1 = sign(pt, v1, v2);
|
|
168476
|
-
const d2 = sign(pt, v2, v3);
|
|
168477
|
-
const d3 = sign(pt, v3, v1);
|
|
168478
|
-
|
|
168479
|
-
const has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
|
|
168480
|
-
const has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
|
|
168481
|
-
|
|
168482
|
-
return !(has_neg && has_pos);
|
|
168483
|
-
};
|
|
168484
|
-
})();
|
|
168485
|
-
|
|
168486
|
-
const baseTriangles = [ ];
|
|
168487
|
-
|
|
168488
|
-
const vertices = (isCCW ? polygonVertices : polygonVertices.slice(0).reverse()).map(i => ({ idx: i }));
|
|
168489
|
-
vertices.forEach((v, i) => {
|
|
168490
|
-
v.prev = vertices[(i - 1 + vertices.length) % vertices.length];
|
|
168491
|
-
v.next = vertices[(i + 1) % vertices.length];
|
|
168492
|
-
});
|
|
168493
|
-
|
|
168494
|
-
const ba = math.vec2();
|
|
168495
|
-
const bc = math.vec2();
|
|
168496
|
-
|
|
168497
|
-
while (vertices.length > 2) {
|
|
168498
|
-
let earIdx = 0;
|
|
168499
|
-
while (true) {
|
|
168500
|
-
if (earIdx >= vertices.length)
|
|
168501
|
-
{
|
|
168502
|
-
throw `isCCW = ${isCCW}; earIdx = ${earIdx}; len = ${vertices.length}`;
|
|
168503
|
-
}
|
|
168504
|
-
const v = vertices[earIdx];
|
|
168505
|
-
|
|
168506
|
-
const a = planeCoords[v.prev.idx];
|
|
168507
|
-
const b = planeCoords[v.idx];
|
|
168508
|
-
const c = planeCoords[v.next.idx];
|
|
168509
|
-
|
|
168510
|
-
math.subVec2(a, b, ba);
|
|
168511
|
-
math.subVec2(c, b, bc);
|
|
168512
|
-
|
|
168513
|
-
if (((ba[0] * bc[1] - ba[1] * bc[0]) >= 0) // a convex vertex
|
|
168514
|
-
&&
|
|
168515
|
-
vertices.every( // no other vertices inside
|
|
168516
|
-
vv => ((vv === v)
|
|
168517
|
-
||
|
|
168518
|
-
(vv === v.prev)
|
|
168519
|
-
||
|
|
168520
|
-
(vv === v.next)
|
|
168521
|
-
||
|
|
168522
|
-
!pointInTriangle(planeCoords[vv.idx], a, b, c))))
|
|
168523
|
-
break;
|
|
168524
|
-
++earIdx;
|
|
168525
|
-
}
|
|
168526
|
-
|
|
168527
|
-
const ear = vertices[earIdx];
|
|
168528
|
-
vertices.splice(earIdx, 1);
|
|
168529
|
-
|
|
168530
|
-
baseTriangles.push([ ear.idx, ear.next.idx, ear.prev.idx ]);
|
|
168531
|
-
|
|
168532
|
-
const prev = ear.prev;
|
|
168533
|
-
prev.next = ear.next;
|
|
168534
|
-
const next = ear.next;
|
|
168535
|
-
next.prev = ear.prev;
|
|
168536
|
-
}
|
|
168537
|
-
|
|
168538
|
-
return [ planeCoords, baseTriangles, isCCW ];
|
|
168539
|
-
};
|
|
168540
|
-
|
|
168541
|
-
const marker3D = function(scene, color) {
|
|
168542
|
-
const marker = new Dot3D(scene, {}, scene.canvas.canvas.parentNode, {
|
|
168543
|
-
borderColor: "white",
|
|
168544
|
-
fillColor: color,
|
|
168545
|
-
zIndex: 100
|
|
168546
|
-
});
|
|
168547
|
-
|
|
168548
|
-
return {
|
|
168549
|
-
update: function(worldPos) {
|
|
168550
|
-
if (worldPos)
|
|
168551
|
-
{
|
|
168552
|
-
marker.worldPos = worldPos;
|
|
168553
|
-
}
|
|
168554
|
-
marker.setVisible(!!worldPos);
|
|
168555
|
-
},
|
|
168556
|
-
|
|
168557
|
-
setHighlighted: h => marker.setHighlighted(h),
|
|
168558
|
-
getCanvasPos: () => marker.canvasPos,
|
|
168559
|
-
getWorldPos: () => marker.worldPos,
|
|
168560
|
-
destroy: () => marker.destroy()
|
|
168561
|
-
};
|
|
168562
|
-
};
|
|
168563
|
-
|
|
168564
|
-
const wire3D = function(scene, color, startWorldPos) {
|
|
168565
|
-
const wire = new Wire3D(scene, scene.canvas.canvas.ownerDocument.body, {
|
|
168566
|
-
color: color,
|
|
168567
|
-
thickness: 1,
|
|
168568
|
-
thicknessClickable: 6
|
|
168569
|
-
});
|
|
168570
|
-
wire.setVisible(false);
|
|
168571
|
-
return {
|
|
168572
|
-
update: endWorldPos => {
|
|
168573
|
-
if (endWorldPos)
|
|
168574
|
-
{
|
|
168575
|
-
wire.setEnds(startWorldPos, endWorldPos);
|
|
168576
|
-
}
|
|
168577
|
-
wire.setVisible(!!endWorldPos);
|
|
168578
|
-
},
|
|
168579
|
-
|
|
168580
|
-
destroy: () => wire.destroy()
|
|
168581
|
-
};
|
|
168582
|
-
};
|
|
168583
|
-
|
|
168584
169049
|
const basePolygon3D = function(scene, color, alpha) {
|
|
168585
169050
|
let mesh = null;
|
|
168586
169051
|
|
|
@@ -169560,7 +170025,8 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
|
|
|
169560
170025
|
|
|
169561
170026
|
(function selectNextPoint(markers) {
|
|
169562
170027
|
const marker = marker3D(scene, zoneColor);
|
|
169563
|
-
const wire = (markers.length > 0) && wire3D(scene, zoneColor
|
|
170028
|
+
const wire = (markers.length > 0) && wire3D(scene, zoneColor);
|
|
170029
|
+
const wireStart = wire && markers[markers.length - 1].getWorldPos();
|
|
169564
170030
|
|
|
169565
170031
|
cleanups.push(() => {
|
|
169566
170032
|
marker.destroy();
|
|
@@ -169620,7 +170086,7 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
|
|
|
169620
170086
|
() => {
|
|
169621
170087
|
updatePointerLens(null);
|
|
169622
170088
|
marker.update(null);
|
|
169623
|
-
wire && wire.update(null);
|
|
170089
|
+
wire && wire.update(wireStart, null);
|
|
169624
170090
|
basePolygon.updateBase((markers.length > 2) ? markers.map(m => m.getWorldPos()) : null);
|
|
169625
170091
|
},
|
|
169626
170092
|
(canvasPos, worldPos) => {
|
|
@@ -169628,7 +170094,7 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
|
|
|
169628
170094
|
firstMarker && firstMarker.setHighlighted(!! snappedFirst);
|
|
169629
170095
|
updatePointerLens(snappedFirst ? snappedFirst.canvasPos : canvasPos);
|
|
169630
170096
|
marker.update((! snappedFirst) && worldPos);
|
|
169631
|
-
wire && wire.update(snappedFirst ? snappedFirst.worldPos : worldPos);
|
|
170097
|
+
wire && wire.update(wireStart, snappedFirst ? snappedFirst.worldPos : worldPos);
|
|
169632
170098
|
if ((markers.length >= 2))
|
|
169633
170099
|
{
|
|
169634
170100
|
const pos = markers.map(m => m.getWorldPos()).concat(snappedFirst ? [] : [worldPos]);
|
|
@@ -169672,7 +170138,7 @@ const startPolysurfaceZoneCreateUI = function(scene, zoneAltitude, zoneHeight, z
|
|
|
169672
170138
|
else
|
|
169673
170139
|
{
|
|
169674
170140
|
marker.update(worldPos);
|
|
169675
|
-
wire && wire.update(worldPos);
|
|
170141
|
+
wire && wire.update(wireStart, worldPos);
|
|
169676
170142
|
selectNextPoint(markers.concat(marker));
|
|
169677
170143
|
}
|
|
169678
170144
|
});
|
|
@@ -170290,6 +170756,8 @@ exports.ZonesPolysurfaceTouchControl = ZonesPolysurfaceTouchControl;
|
|
|
170290
170756
|
exports.ZonesTouchControl = ZonesTouchControl;
|
|
170291
170757
|
exports.activateDraggableDot = activateDraggableDot;
|
|
170292
170758
|
exports.activateDraggableDots = activateDraggableDots;
|
|
170759
|
+
exports.addMousePressListener = addMousePressListener;
|
|
170760
|
+
exports.addTouchPressListener = addTouchPressListener;
|
|
170293
170761
|
exports.buildBoxGeometry = buildBoxGeometry;
|
|
170294
170762
|
exports.buildBoxLinesGeometry = buildBoxLinesGeometry;
|
|
170295
170763
|
exports.buildBoxLinesGeometryFromAABB = buildBoxLinesGeometryFromAABB;
|
|
@@ -170309,6 +170777,7 @@ exports.getPlaneRTCPos = getPlaneRTCPos;
|
|
|
170309
170777
|
exports.isTriangleMeshSolid = isTriangleMeshSolid;
|
|
170310
170778
|
exports.load3DSGeometry = load3DSGeometry;
|
|
170311
170779
|
exports.loadOBJGeometry = loadOBJGeometry;
|
|
170780
|
+
exports.marker3D = marker3D;
|
|
170312
170781
|
exports.math = math;
|
|
170313
170782
|
exports.meshSurfaceArea = meshSurfaceArea;
|
|
170314
170783
|
exports.meshVolume = meshVolume;
|
|
@@ -170316,9 +170785,12 @@ exports.os = os;
|
|
|
170316
170785
|
exports.rtcToWorldPos = rtcToWorldPos;
|
|
170317
170786
|
exports.sRGBEncoding = sRGBEncoding;
|
|
170318
170787
|
exports.setFrustum = setFrustum;
|
|
170788
|
+
exports.startPolygonCreate = startPolygonCreate;
|
|
170319
170789
|
exports.stats = stats;
|
|
170320
170790
|
exports.touchPointSelector = touchPointSelector;
|
|
170321
170791
|
exports.transformToNode = transformToNode;
|
|
170792
|
+
exports.triangulateEarClipping = triangulateEarClipping;
|
|
170322
170793
|
exports.utils = utils;
|
|
170794
|
+
exports.wire3D = wire3D;
|
|
170323
170795
|
exports.worldToRTCPos = worldToRTCPos;
|
|
170324
170796
|
exports.worldToRTCPositions = worldToRTCPositions;
|