@inweb/viewer-three 27.2.1 → 27.2.3
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/viewer-three.js +704 -339
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +703 -338
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/controls/WalkControls.d.ts +8 -0
- package/lib/Viewer/draggers/CuttingPlaneDragger.d.ts +30 -8
- package/lib/Viewer/helpers/PlaneHelper2.d.ts +12 -0
- package/lib/Viewer/measurement/Snapper.d.ts +1 -1
- package/package.json +5 -5
- package/src/Viewer/Viewer.ts +4 -0
- package/src/Viewer/components/SelectionComponent.ts +1 -1
- package/src/Viewer/controls/WalkControls.ts +50 -4
- package/src/Viewer/draggers/CuttingPlaneDragger.ts +243 -42
- package/src/Viewer/draggers/CuttingPlaneXAxis.ts +2 -3
- package/src/Viewer/draggers/CuttingPlaneYAxis.ts +2 -3
- package/src/Viewer/draggers/CuttingPlaneZAxis.ts +2 -3
- package/src/Viewer/draggers/index.ts +2 -0
- package/src/Viewer/helpers/{PlaneHelper.ts → PlaneHelper2.ts} +27 -31
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +413 -189
- package/src/Viewer/measurement/Snapper.ts +13 -5
- package/lib/Viewer/helpers/PlaneHelper.d.ts +0 -11
package/dist/viewer-three.js
CHANGED
|
@@ -21255,7 +21255,7 @@
|
|
|
21255
21255
|
this.material.dispose();
|
|
21256
21256
|
}
|
|
21257
21257
|
}
|
|
21258
|
-
|
|
21258
|
+
class PlaneHelper extends Line$1 {
|
|
21259
21259
|
constructor( plane, size = 1, hex = 0xffff00 ) {
|
|
21260
21260
|
const color = hex;
|
|
21261
21261
|
const positions = [ 1, -1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
|
|
@@ -21285,7 +21285,7 @@
|
|
|
21285
21285
|
this.children[ 0 ].geometry.dispose();
|
|
21286
21286
|
this.children[ 0 ].material.dispose();
|
|
21287
21287
|
}
|
|
21288
|
-
}
|
|
21288
|
+
}
|
|
21289
21289
|
const _axis = new Vector3();
|
|
21290
21290
|
let _lineGeometry, _coneGeometry;
|
|
21291
21291
|
class ArrowHelper extends Object3D {
|
|
@@ -32455,7 +32455,7 @@ void main() {
|
|
|
32455
32455
|
PerspectiveCamera: PerspectiveCamera,
|
|
32456
32456
|
Plane: Plane,
|
|
32457
32457
|
PlaneGeometry: PlaneGeometry,
|
|
32458
|
-
PlaneHelper: PlaneHelper
|
|
32458
|
+
PlaneHelper: PlaneHelper,
|
|
32459
32459
|
PointLight: PointLight,
|
|
32460
32460
|
PointLightHelper: PointLightHelper,
|
|
32461
32461
|
Points: Points,
|
|
@@ -33644,47 +33644,6 @@ void main() {
|
|
|
33644
33644
|
}
|
|
33645
33645
|
}
|
|
33646
33646
|
|
|
33647
|
-
class PlaneHelper extends Line$1 {
|
|
33648
|
-
constructor(plane, size = 1, color = 0xffff00, offset = new Vector3()) {
|
|
33649
|
-
const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0];
|
|
33650
|
-
const geometry = new BufferGeometry();
|
|
33651
|
-
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
33652
|
-
geometry.computeBoundingSphere();
|
|
33653
|
-
super(geometry, new LineBasicMaterial({ color, toneMapped: false }));
|
|
33654
|
-
this.type = "PlaneHelper";
|
|
33655
|
-
this.plane = plane;
|
|
33656
|
-
this.size = size;
|
|
33657
|
-
this.offset = offset;
|
|
33658
|
-
const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
|
|
33659
|
-
const geometry2 = new BufferGeometry();
|
|
33660
|
-
geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
|
|
33661
|
-
geometry2.computeBoundingSphere();
|
|
33662
|
-
this.helper = new Mesh(geometry2, new MeshBasicMaterial({
|
|
33663
|
-
color,
|
|
33664
|
-
opacity: 0.2,
|
|
33665
|
-
transparent: true,
|
|
33666
|
-
depthWrite: false,
|
|
33667
|
-
toneMapped: false,
|
|
33668
|
-
side: DoubleSide,
|
|
33669
|
-
}));
|
|
33670
|
-
this.add(this.helper);
|
|
33671
|
-
}
|
|
33672
|
-
dispose() {
|
|
33673
|
-
this.geometry.dispose();
|
|
33674
|
-
this.material.dispose();
|
|
33675
|
-
this.children[0].geometry.dispose();
|
|
33676
|
-
this.children[0].material.dispose();
|
|
33677
|
-
}
|
|
33678
|
-
updateMatrixWorld(force) {
|
|
33679
|
-
this.position.set(0, 0, 0);
|
|
33680
|
-
this.lookAt(this.plane.normal);
|
|
33681
|
-
this.position.copy(this.offset);
|
|
33682
|
-
this.translateZ(-(this.offset.dot(this.plane.normal) + this.plane.constant));
|
|
33683
|
-
this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
|
|
33684
|
-
super.updateMatrixWorld(force);
|
|
33685
|
-
}
|
|
33686
|
-
}
|
|
33687
|
-
|
|
33688
33647
|
const _changeEvent = { type: "change" };
|
|
33689
33648
|
const _startEvent = { type: "start" };
|
|
33690
33649
|
const _endEvent = { type: "end" };
|
|
@@ -34343,6 +34302,166 @@ void main() {
|
|
|
34343
34302
|
}
|
|
34344
34303
|
}
|
|
34345
34304
|
|
|
34305
|
+
class PlaneHelper2 extends Object3D {
|
|
34306
|
+
constructor(size = 1, color = 0xf0f0f0, opacity = 0.15) {
|
|
34307
|
+
super();
|
|
34308
|
+
this.type = "PlaneHelper2";
|
|
34309
|
+
this.size = size;
|
|
34310
|
+
const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0];
|
|
34311
|
+
const geometry = new BufferGeometry();
|
|
34312
|
+
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
34313
|
+
geometry.computeBoundingSphere();
|
|
34314
|
+
this.outline = new Line$1(geometry, new LineBasicMaterial({ color, toneMapped: false }));
|
|
34315
|
+
const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
|
|
34316
|
+
const geometry2 = new BufferGeometry();
|
|
34317
|
+
geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
|
|
34318
|
+
geometry2.computeBoundingSphere();
|
|
34319
|
+
this.mesh = new Mesh(geometry2, new MeshBasicMaterial({
|
|
34320
|
+
color,
|
|
34321
|
+
opacity,
|
|
34322
|
+
transparent: true,
|
|
34323
|
+
depthWrite: false,
|
|
34324
|
+
toneMapped: false,
|
|
34325
|
+
side: DoubleSide,
|
|
34326
|
+
}));
|
|
34327
|
+
this.add(this.outline);
|
|
34328
|
+
this.add(this.mesh);
|
|
34329
|
+
}
|
|
34330
|
+
dispose() {
|
|
34331
|
+
this.outline.geometry.dispose();
|
|
34332
|
+
this.outline.material.dispose();
|
|
34333
|
+
this.mesh.geometry.dispose();
|
|
34334
|
+
this.mesh.material.dispose();
|
|
34335
|
+
}
|
|
34336
|
+
updateMatrixWorld(force) {
|
|
34337
|
+
this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
|
|
34338
|
+
super.updateMatrixWorld(force);
|
|
34339
|
+
}
|
|
34340
|
+
getLineMaterial() {
|
|
34341
|
+
return this.outline.material;
|
|
34342
|
+
}
|
|
34343
|
+
getMeshMaterial() {
|
|
34344
|
+
return this.mesh.material;
|
|
34345
|
+
}
|
|
34346
|
+
}
|
|
34347
|
+
|
|
34348
|
+
const DESKTOP_SNAP_DISTANCE = 10;
|
|
34349
|
+
const MOBILE_SNAP_DISTANCE = 50;
|
|
34350
|
+
const _vertex = new Vector3();
|
|
34351
|
+
const _start$1 = new Vector3();
|
|
34352
|
+
const _end$1 = new Vector3();
|
|
34353
|
+
const _line = new Line3();
|
|
34354
|
+
const _center = new Vector3();
|
|
34355
|
+
const _projection = new Vector3();
|
|
34356
|
+
class Snapper {
|
|
34357
|
+
constructor(camera, renderer, canvas) {
|
|
34358
|
+
this.camera = camera;
|
|
34359
|
+
this.renderer = renderer;
|
|
34360
|
+
this.canvas = canvas;
|
|
34361
|
+
this.threshold = 0.0001;
|
|
34362
|
+
this.raycaster = new Raycaster();
|
|
34363
|
+
this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
|
|
34364
|
+
this.edgesCache = new WeakMap();
|
|
34365
|
+
}
|
|
34366
|
+
isMobile() {
|
|
34367
|
+
if (typeof navigator === "undefined")
|
|
34368
|
+
return false;
|
|
34369
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
|
|
34370
|
+
}
|
|
34371
|
+
getMousePosition(event, target) {
|
|
34372
|
+
return target.set(event.clientX, event.clientY);
|
|
34373
|
+
}
|
|
34374
|
+
getPointerIntersects(mouse, objects, recursive = false, clip = true) {
|
|
34375
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
34376
|
+
const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
|
|
34377
|
+
const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
|
|
34378
|
+
const coords = new Vector2(x, y);
|
|
34379
|
+
this.raycaster.setFromCamera(coords, this.camera);
|
|
34380
|
+
this.raycaster.params = {
|
|
34381
|
+
Mesh: {},
|
|
34382
|
+
Line: { threshold: this.threshold },
|
|
34383
|
+
Line2: { threshold: this.threshold },
|
|
34384
|
+
LOD: {},
|
|
34385
|
+
Points: { threshold: this.threshold },
|
|
34386
|
+
Sprite: {},
|
|
34387
|
+
};
|
|
34388
|
+
let intersects = this.raycaster.intersectObjects(objects, recursive);
|
|
34389
|
+
if (clip) {
|
|
34390
|
+
const clippingPlanes = this.renderer.clippingPlanes || [];
|
|
34391
|
+
clippingPlanes.forEach((plane) => {
|
|
34392
|
+
intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
|
|
34393
|
+
});
|
|
34394
|
+
}
|
|
34395
|
+
return intersects;
|
|
34396
|
+
}
|
|
34397
|
+
getDetectRadius(point) {
|
|
34398
|
+
const camera = this.camera;
|
|
34399
|
+
if (camera.isOrthographicCamera) {
|
|
34400
|
+
const fieldHeight = (camera.top - camera.bottom) / camera.zoom;
|
|
34401
|
+
const canvasHeight = this.canvas.height;
|
|
34402
|
+
const worldUnitsPerPixel = fieldHeight / canvasHeight;
|
|
34403
|
+
return this.detectRadiusInPixels * worldUnitsPerPixel;
|
|
34404
|
+
}
|
|
34405
|
+
if (camera.isPerspectiveCamera) {
|
|
34406
|
+
const distance = camera.position.distanceTo(point);
|
|
34407
|
+
const fieldHeight = 2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5)) * distance;
|
|
34408
|
+
const canvasHeight = this.canvas.height;
|
|
34409
|
+
const worldUnitsPerPixel = fieldHeight / canvasHeight;
|
|
34410
|
+
return this.detectRadiusInPixels * worldUnitsPerPixel;
|
|
34411
|
+
}
|
|
34412
|
+
return 0.1;
|
|
34413
|
+
}
|
|
34414
|
+
getSnapPoint(mouse, objects) {
|
|
34415
|
+
const intersections = this.getPointerIntersects(mouse, objects);
|
|
34416
|
+
if (intersections.length === 0)
|
|
34417
|
+
return undefined;
|
|
34418
|
+
const object = intersections[0].object;
|
|
34419
|
+
const intersectionPoint = intersections[0].point;
|
|
34420
|
+
const localPoint = object.worldToLocal(intersectionPoint.clone());
|
|
34421
|
+
let snapPoint;
|
|
34422
|
+
let snapDistance = this.getDetectRadius(intersectionPoint);
|
|
34423
|
+
const geometry = object.geometry;
|
|
34424
|
+
const positions = geometry.attributes.position.array;
|
|
34425
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
34426
|
+
_vertex.set(positions[i], positions[i + 1], positions[i + 2]);
|
|
34427
|
+
const distance = _vertex.distanceTo(localPoint);
|
|
34428
|
+
if (distance < snapDistance) {
|
|
34429
|
+
snapDistance = distance;
|
|
34430
|
+
snapPoint = _vertex.clone();
|
|
34431
|
+
}
|
|
34432
|
+
}
|
|
34433
|
+
if (snapPoint)
|
|
34434
|
+
return object.localToWorld(snapPoint);
|
|
34435
|
+
let edges = this.edgesCache.get(geometry);
|
|
34436
|
+
if (!edges) {
|
|
34437
|
+
edges = new EdgesGeometry(geometry);
|
|
34438
|
+
this.edgesCache.set(geometry, edges);
|
|
34439
|
+
}
|
|
34440
|
+
const edgePositions = edges.attributes.position.array;
|
|
34441
|
+
for (let i = 0; i < edgePositions.length; i += 6) {
|
|
34442
|
+
_start$1.set(edgePositions[i], edgePositions[i + 1], edgePositions[i + 2]);
|
|
34443
|
+
_end$1.set(edgePositions[i + 3], edgePositions[i + 4], edgePositions[i + 5]);
|
|
34444
|
+
_line.set(_start$1, _end$1);
|
|
34445
|
+
_line.getCenter(_center);
|
|
34446
|
+
const centerDistance = _center.distanceTo(localPoint);
|
|
34447
|
+
if (centerDistance < snapDistance) {
|
|
34448
|
+
snapDistance = centerDistance;
|
|
34449
|
+
snapPoint = _center.clone();
|
|
34450
|
+
continue;
|
|
34451
|
+
}
|
|
34452
|
+
_line.closestPointToPoint(localPoint, true, _projection);
|
|
34453
|
+
const lineDistance = _projection.distanceTo(localPoint);
|
|
34454
|
+
if (lineDistance < snapDistance) {
|
|
34455
|
+
snapDistance = lineDistance;
|
|
34456
|
+
snapPoint = _projection.clone();
|
|
34457
|
+
}
|
|
34458
|
+
}
|
|
34459
|
+
if (snapPoint)
|
|
34460
|
+
return object.localToWorld(snapPoint);
|
|
34461
|
+
return intersectionPoint.clone();
|
|
34462
|
+
}
|
|
34463
|
+
}
|
|
34464
|
+
|
|
34346
34465
|
class OrbitDragger {
|
|
34347
34466
|
constructor(viewer) {
|
|
34348
34467
|
this.updateControls = () => {
|
|
@@ -34435,52 +34554,129 @@ void main() {
|
|
|
34435
34554
|
}
|
|
34436
34555
|
|
|
34437
34556
|
class CuttingPlaneDragger extends OrbitDragger {
|
|
34438
|
-
constructor(viewer
|
|
34557
|
+
constructor(viewer) {
|
|
34439
34558
|
super(viewer);
|
|
34559
|
+
this.helpers = [];
|
|
34560
|
+
this.activeHelper = null;
|
|
34440
34561
|
this.transformChange = () => {
|
|
34441
|
-
|
|
34562
|
+
if (!this.activeHelper)
|
|
34563
|
+
return;
|
|
34564
|
+
const plane = this.activeHelper.plane;
|
|
34565
|
+
plane.normal.copy(new Vector3(0, 0, -1)).applyQuaternion(this.activeHelper.quaternion);
|
|
34566
|
+
plane.constant = -this.activeHelper.position.dot(plane.normal);
|
|
34442
34567
|
this.viewer.update();
|
|
34568
|
+
this.changed = true;
|
|
34569
|
+
};
|
|
34570
|
+
this.translateDrag = (event) => {
|
|
34571
|
+
this.orbit.enabled = !event.value;
|
|
34572
|
+
this.rotate.enabled = !event.value;
|
|
34443
34573
|
};
|
|
34444
|
-
this.
|
|
34574
|
+
this.rotateDrag = (event) => {
|
|
34445
34575
|
this.orbit.enabled = !event.value;
|
|
34576
|
+
this.translate.enabled = !event.value;
|
|
34446
34577
|
};
|
|
34447
34578
|
this.updatePlaneSize = () => {
|
|
34448
|
-
|
|
34579
|
+
const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34580
|
+
this.helpers.forEach((planeHelper) => (planeHelper.size = extentsSize));
|
|
34449
34581
|
this.viewer.update();
|
|
34450
34582
|
};
|
|
34451
34583
|
this.updateTransformCamera = () => {
|
|
34452
|
-
this.
|
|
34584
|
+
this.translate.camera = this.viewer.camera;
|
|
34585
|
+
this.rotate.camera = this.viewer.camera;
|
|
34586
|
+
this.snapper.camera = this.viewer.camera;
|
|
34587
|
+
};
|
|
34588
|
+
this.clearHelpers = () => {
|
|
34589
|
+
this.setActiveHelper();
|
|
34590
|
+
this.helpers.forEach((helper) => {
|
|
34591
|
+
helper.removeFromParent();
|
|
34592
|
+
helper.dispose();
|
|
34593
|
+
});
|
|
34594
|
+
this.helpers = [];
|
|
34595
|
+
this.viewer.update();
|
|
34596
|
+
};
|
|
34597
|
+
this.onKeyDown = (event) => {
|
|
34598
|
+
if (event.key === "Shift")
|
|
34599
|
+
this.rotate.setRotationSnap(Math.PI / 4);
|
|
34600
|
+
if (event.key === "Delete" || event.key === "Backspace")
|
|
34601
|
+
this.deleteActivePlane();
|
|
34602
|
+
if (event.key === "Escape" && (this.translate.dragging || this.rotate.dragging))
|
|
34603
|
+
this.reset();
|
|
34604
|
+
};
|
|
34605
|
+
this.onKeyUp = (event) => {
|
|
34606
|
+
if (event.key === "Shift")
|
|
34607
|
+
this.rotate.setRotationSnap(null);
|
|
34608
|
+
};
|
|
34609
|
+
this.onPointerDown = (event) => {
|
|
34610
|
+
if (event.button !== 0 || !event.isPrimary)
|
|
34611
|
+
return;
|
|
34612
|
+
this.snapper.getMousePosition(event, this.downPosition);
|
|
34613
|
+
this.saveState();
|
|
34614
|
+
};
|
|
34615
|
+
this.onPointerUp = (event) => {
|
|
34616
|
+
if (event.button !== 0)
|
|
34617
|
+
return;
|
|
34618
|
+
const upPosition = this.snapper.getMousePosition(event, new Vector2());
|
|
34619
|
+
if (upPosition.distanceTo(this.downPosition) !== 0)
|
|
34620
|
+
return;
|
|
34621
|
+
const intersects = this.snapper.getPointerIntersects(upPosition, this.helpers, true, false);
|
|
34622
|
+
if (intersects.length === 0)
|
|
34623
|
+
return;
|
|
34624
|
+
this.setActiveHelper(intersects[0].object.parent);
|
|
34625
|
+
};
|
|
34626
|
+
this.onPointerCancel = (event) => {
|
|
34627
|
+
this.viewer.canvas.dispatchEvent(new PointerEvent("pointerup", event));
|
|
34453
34628
|
};
|
|
34454
34629
|
this.onDoubleClick = (event) => {
|
|
34630
|
+
if (!this.activeHelper)
|
|
34631
|
+
return;
|
|
34632
|
+
const mousePosition = this.snapper.getMousePosition(event, new Vector2());
|
|
34633
|
+
const intersects = this.snapper.getPointerIntersects(mousePosition, [this.activeHelper], true, false);
|
|
34634
|
+
if (intersects.length === 0)
|
|
34635
|
+
return;
|
|
34636
|
+
this.activeHelper.rotateOnAxis(new Vector3(0, 1, 0), Math.PI);
|
|
34637
|
+
this.transformChange();
|
|
34455
34638
|
event.stopPropagation();
|
|
34456
|
-
this.plane.negate();
|
|
34457
|
-
this.viewer.update();
|
|
34458
34639
|
};
|
|
34459
|
-
const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34460
|
-
const extentsCenter = viewer.extents.getCenter(new Vector3());
|
|
34461
|
-
const constant = -extentsCenter.dot(normal);
|
|
34462
|
-
this.plane = new Plane(normal, constant);
|
|
34463
34640
|
if (!viewer.renderer.clippingPlanes)
|
|
34464
34641
|
viewer.renderer.clippingPlanes = [];
|
|
34465
|
-
viewer.renderer.clippingPlanes
|
|
34466
|
-
this.
|
|
34467
|
-
|
|
34468
|
-
this.
|
|
34469
|
-
this.
|
|
34470
|
-
this.
|
|
34471
|
-
this.
|
|
34472
|
-
this.
|
|
34473
|
-
this.
|
|
34474
|
-
this.
|
|
34475
|
-
this.
|
|
34476
|
-
this.
|
|
34477
|
-
this.
|
|
34478
|
-
this.
|
|
34642
|
+
this.clippingPlanes = viewer.renderer.clippingPlanes;
|
|
34643
|
+
this.clippingPlanes.forEach((plane) => this.addHelper(plane));
|
|
34644
|
+
const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34645
|
+
this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
|
|
34646
|
+
this.snapper.threshold = extentsSize / 10000;
|
|
34647
|
+
this.downPosition = new Vector2();
|
|
34648
|
+
this.position0 = new Vector3();
|
|
34649
|
+
this.quaternion0 = new Quaternion();
|
|
34650
|
+
this.translate = new TransformControls(viewer.camera, viewer.canvas);
|
|
34651
|
+
this.translate.setMode("translate");
|
|
34652
|
+
this.translate.setSpace("local");
|
|
34653
|
+
this.translate.showX = false;
|
|
34654
|
+
this.translate.showY = false;
|
|
34655
|
+
this.translate.showZ = true;
|
|
34656
|
+
this.translate.addEventListener("change", this.transformChange);
|
|
34657
|
+
this.translate.addEventListener("dragging-changed", this.translateDrag);
|
|
34658
|
+
this.viewer.helpers.add(this.translate.getHelper());
|
|
34659
|
+
this.rotate = new TransformControls(viewer.camera, viewer.canvas);
|
|
34660
|
+
this.rotate.setMode("rotate");
|
|
34661
|
+
this.rotate.setSpace("local");
|
|
34662
|
+
this.rotate.showX = true;
|
|
34663
|
+
this.rotate.showY = true;
|
|
34664
|
+
this.rotate.showZ = false;
|
|
34665
|
+
this.rotate.addEventListener("change", this.transformChange);
|
|
34666
|
+
this.rotate.addEventListener("dragging-changed", this.rotateDrag);
|
|
34667
|
+
this.viewer.helpers.add(this.rotate.getHelper());
|
|
34668
|
+
this.setActiveHelper(this.helpers[this.helpers.length - 1]);
|
|
34479
34669
|
this.viewer.addEventListener("explode", this.updatePlaneSize);
|
|
34480
34670
|
this.viewer.addEventListener("show", this.updatePlaneSize);
|
|
34481
34671
|
this.viewer.addEventListener("showall", this.updatePlaneSize);
|
|
34482
34672
|
this.viewer.addEventListener("changecameramode", this.updateTransformCamera);
|
|
34673
|
+
this.viewer.addEventListener("clearslices", this.clearHelpers);
|
|
34674
|
+
this.viewer.canvas.addEventListener("pointerdown", this.onPointerDown, true);
|
|
34675
|
+
this.viewer.canvas.addEventListener("pointerup", this.onPointerUp, true);
|
|
34676
|
+
this.viewer.canvas.addEventListener("pointercancel", this.onPointerCancel, true);
|
|
34483
34677
|
this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
|
|
34678
|
+
window.addEventListener("keydown", this.onKeyDown);
|
|
34679
|
+
window.addEventListener("keyup", this.onKeyUp);
|
|
34484
34680
|
this.viewer.update();
|
|
34485
34681
|
}
|
|
34486
34682
|
dispose() {
|
|
@@ -34488,34 +34684,125 @@ void main() {
|
|
|
34488
34684
|
this.viewer.removeEventListener("show", this.updatePlaneSize);
|
|
34489
34685
|
this.viewer.removeEventListener("showall", this.updatePlaneSize);
|
|
34490
34686
|
this.viewer.removeEventListener("changecameramode", this.updateTransformCamera);
|
|
34687
|
+
this.viewer.removeEventListener("clearslices", this.clearHelpers);
|
|
34688
|
+
this.viewer.canvas.removeEventListener("pointerdown", this.onPointerDown, true);
|
|
34689
|
+
this.viewer.canvas.removeEventListener("pointerup", this.onPointerUp, true);
|
|
34690
|
+
this.viewer.canvas.removeEventListener("pointercancel", this.onPointerCancel, true);
|
|
34491
34691
|
this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
|
|
34492
|
-
|
|
34493
|
-
|
|
34494
|
-
this.
|
|
34495
|
-
this.
|
|
34496
|
-
this.
|
|
34497
|
-
this.
|
|
34498
|
-
this.
|
|
34499
|
-
this.
|
|
34692
|
+
window.removeEventListener("keydown", this.onKeyDown);
|
|
34693
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
34694
|
+
this.translate.removeEventListener("change", this.transformChange);
|
|
34695
|
+
this.translate.removeEventListener("dragging-changed", this.translateDrag);
|
|
34696
|
+
this.translate.getHelper().removeFromParent();
|
|
34697
|
+
this.translate.detach();
|
|
34698
|
+
this.translate.dispose();
|
|
34699
|
+
this.rotate.removeEventListener("change", this.transformChange);
|
|
34700
|
+
this.rotate.removeEventListener("dragging-changed", this.rotateDrag);
|
|
34701
|
+
this.rotate.getHelper().removeFromParent();
|
|
34702
|
+
this.rotate.detach();
|
|
34703
|
+
this.rotate.dispose();
|
|
34704
|
+
this.helpers.forEach((helper) => {
|
|
34705
|
+
helper.removeFromParent();
|
|
34706
|
+
helper.dispose();
|
|
34707
|
+
});
|
|
34708
|
+
this.helpers = [];
|
|
34709
|
+
this.activeHelper = null;
|
|
34500
34710
|
super.dispose();
|
|
34501
34711
|
}
|
|
34712
|
+
addHelper(plane) {
|
|
34713
|
+
const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34714
|
+
const extentsCenter = this.viewer.extents.getCenter(new Vector3());
|
|
34715
|
+
const helper = new PlaneHelper2(extentsSize);
|
|
34716
|
+
helper.plane = plane;
|
|
34717
|
+
helper.position.copy(plane.projectPoint(extentsCenter, new Vector3()));
|
|
34718
|
+
helper.quaternion.setFromUnitVectors(new Vector3(0, 0, -1), plane.normal);
|
|
34719
|
+
this.helpers.push(helper);
|
|
34720
|
+
this.viewer.helpers.add(helper);
|
|
34721
|
+
return helper;
|
|
34722
|
+
}
|
|
34723
|
+
setActiveHelper(helper) {
|
|
34724
|
+
if (helper === this.activeHelper)
|
|
34725
|
+
return;
|
|
34726
|
+
if (this.activeHelper) {
|
|
34727
|
+
this.activeHelper.getLineMaterial().color.setHex(0xf0f0f0);
|
|
34728
|
+
this.activeHelper.getMeshMaterial().opacity = 0.15;
|
|
34729
|
+
this.translate.detach();
|
|
34730
|
+
this.rotate.detach();
|
|
34731
|
+
}
|
|
34732
|
+
this.activeHelper = helper;
|
|
34733
|
+
if (this.activeHelper) {
|
|
34734
|
+
this.activeHelper.getLineMaterial().color.setHex(0xd0d0d0);
|
|
34735
|
+
this.activeHelper.getMeshMaterial().opacity = 0.3;
|
|
34736
|
+
this.translate.attach(this.activeHelper);
|
|
34737
|
+
this.rotate.attach(this.activeHelper);
|
|
34738
|
+
}
|
|
34739
|
+
this.viewer.update();
|
|
34740
|
+
}
|
|
34741
|
+
saveState() {
|
|
34742
|
+
if (!this.activeHelper)
|
|
34743
|
+
return;
|
|
34744
|
+
this.position0.copy(this.activeHelper.position);
|
|
34745
|
+
this.quaternion0.copy(this.activeHelper.quaternion);
|
|
34746
|
+
}
|
|
34747
|
+
reset() {
|
|
34748
|
+
if (!this.activeHelper)
|
|
34749
|
+
return;
|
|
34750
|
+
this.translate.dragging = false;
|
|
34751
|
+
this.rotate.dragging = false;
|
|
34752
|
+
this.orbit.state = STATE.NONE;
|
|
34753
|
+
this.activeHelper.position.copy(this.position0);
|
|
34754
|
+
this.activeHelper.quaternion.copy(this.quaternion0);
|
|
34755
|
+
this.transformChange();
|
|
34756
|
+
}
|
|
34757
|
+
addPlane(normal) {
|
|
34758
|
+
const extentsCenter = this.viewer.extents.getCenter(new Vector3());
|
|
34759
|
+
const constant = -extentsCenter.dot(normal);
|
|
34760
|
+
const plane = new Plane(normal, constant);
|
|
34761
|
+
this.clippingPlanes.push(plane);
|
|
34762
|
+
const helper = this.addHelper(plane);
|
|
34763
|
+
this.setActiveHelper(helper);
|
|
34764
|
+
}
|
|
34765
|
+
addPlaneX() {
|
|
34766
|
+
this.addPlane(new Vector3(-1, 0, 0));
|
|
34767
|
+
}
|
|
34768
|
+
addPlaneY() {
|
|
34769
|
+
this.addPlane(new Vector3(0, -1, 0));
|
|
34770
|
+
}
|
|
34771
|
+
addPlaneZ() {
|
|
34772
|
+
this.addPlane(new Vector3(0, 0, -1));
|
|
34773
|
+
}
|
|
34774
|
+
deleteActivePlane() {
|
|
34775
|
+
if (!this.activeHelper)
|
|
34776
|
+
return;
|
|
34777
|
+
const helper = this.activeHelper;
|
|
34778
|
+
const index = this.clippingPlanes.indexOf(helper.plane);
|
|
34779
|
+
if (index !== -1)
|
|
34780
|
+
this.clippingPlanes.splice(index, 1);
|
|
34781
|
+
this.helpers = this.helpers.filter((x) => x !== helper);
|
|
34782
|
+
helper.removeFromParent();
|
|
34783
|
+
helper.dispose();
|
|
34784
|
+
this.setActiveHelper(this.helpers[this.helpers.length - 1]);
|
|
34785
|
+
}
|
|
34502
34786
|
}
|
|
34503
34787
|
|
|
34504
34788
|
class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
|
|
34505
34789
|
constructor(viewer) {
|
|
34506
|
-
super(viewer
|
|
34790
|
+
super(viewer);
|
|
34791
|
+
this.addPlaneX();
|
|
34507
34792
|
}
|
|
34508
34793
|
}
|
|
34509
34794
|
|
|
34510
34795
|
class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
|
|
34511
34796
|
constructor(viewer) {
|
|
34512
|
-
super(viewer
|
|
34797
|
+
super(viewer);
|
|
34798
|
+
this.addPlaneY();
|
|
34513
34799
|
}
|
|
34514
34800
|
}
|
|
34515
34801
|
|
|
34516
34802
|
class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
|
|
34517
34803
|
constructor(viewer) {
|
|
34518
|
-
super(viewer
|
|
34804
|
+
super(viewer);
|
|
34805
|
+
this.addPlaneZ();
|
|
34519
34806
|
}
|
|
34520
34807
|
}
|
|
34521
34808
|
|
|
@@ -34592,120 +34879,6 @@ void main() {
|
|
|
34592
34879
|
}
|
|
34593
34880
|
}
|
|
34594
34881
|
|
|
34595
|
-
const DESKTOP_SNAP_DISTANCE = 10;
|
|
34596
|
-
const MOBILE_SNAP_DISTANCE = 50;
|
|
34597
|
-
const _vertex = new Vector3();
|
|
34598
|
-
const _start$1 = new Vector3();
|
|
34599
|
-
const _end$1 = new Vector3();
|
|
34600
|
-
const _line = new Line3();
|
|
34601
|
-
const _center = new Vector3();
|
|
34602
|
-
const _projection = new Vector3();
|
|
34603
|
-
class Snapper {
|
|
34604
|
-
constructor(camera, renderer, canvas) {
|
|
34605
|
-
this.camera = camera;
|
|
34606
|
-
this.renderer = renderer;
|
|
34607
|
-
this.canvas = canvas;
|
|
34608
|
-
this.threshold = 0.0001;
|
|
34609
|
-
this.raycaster = new Raycaster();
|
|
34610
|
-
this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
|
|
34611
|
-
this.edgesCache = new WeakMap();
|
|
34612
|
-
}
|
|
34613
|
-
isMobile() {
|
|
34614
|
-
if (typeof navigator === "undefined")
|
|
34615
|
-
return false;
|
|
34616
|
-
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
|
|
34617
|
-
}
|
|
34618
|
-
getMousePosition(event, target) {
|
|
34619
|
-
return target.set(event.clientX, event.clientY);
|
|
34620
|
-
}
|
|
34621
|
-
getPointerIntersects(mouse, objects) {
|
|
34622
|
-
const rect = this.canvas.getBoundingClientRect();
|
|
34623
|
-
const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
|
|
34624
|
-
const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
|
|
34625
|
-
const coords = new Vector2(x, y);
|
|
34626
|
-
this.raycaster.setFromCamera(coords, this.camera);
|
|
34627
|
-
this.raycaster.params = {
|
|
34628
|
-
Mesh: {},
|
|
34629
|
-
Line: { threshold: this.threshold },
|
|
34630
|
-
Line2: { threshold: this.threshold },
|
|
34631
|
-
LOD: {},
|
|
34632
|
-
Points: { threshold: this.threshold },
|
|
34633
|
-
Sprite: {},
|
|
34634
|
-
};
|
|
34635
|
-
let intersects = this.raycaster.intersectObjects(objects, false);
|
|
34636
|
-
(this.renderer.clippingPlanes || []).forEach((plane) => {
|
|
34637
|
-
intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
|
|
34638
|
-
});
|
|
34639
|
-
return intersects;
|
|
34640
|
-
}
|
|
34641
|
-
getDetectRadius(point) {
|
|
34642
|
-
const camera = this.camera;
|
|
34643
|
-
if (camera.isOrthographicCamera) {
|
|
34644
|
-
const fieldHeight = (camera.top - camera.bottom) / camera.zoom;
|
|
34645
|
-
const canvasHeight = this.canvas.height;
|
|
34646
|
-
const worldUnitsPerPixel = fieldHeight / canvasHeight;
|
|
34647
|
-
return this.detectRadiusInPixels * worldUnitsPerPixel;
|
|
34648
|
-
}
|
|
34649
|
-
if (camera.isPerspectiveCamera) {
|
|
34650
|
-
const distance = camera.position.distanceTo(point);
|
|
34651
|
-
const fieldHeight = 2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5)) * distance;
|
|
34652
|
-
const canvasHeight = this.canvas.height;
|
|
34653
|
-
const worldUnitsPerPixel = fieldHeight / canvasHeight;
|
|
34654
|
-
return this.detectRadiusInPixels * worldUnitsPerPixel;
|
|
34655
|
-
}
|
|
34656
|
-
return 0.1;
|
|
34657
|
-
}
|
|
34658
|
-
getSnapPoint(mouse, objects) {
|
|
34659
|
-
const intersections = this.getPointerIntersects(mouse, objects);
|
|
34660
|
-
if (intersections.length === 0)
|
|
34661
|
-
return undefined;
|
|
34662
|
-
const object = intersections[0].object;
|
|
34663
|
-
const intersectionPoint = intersections[0].point;
|
|
34664
|
-
const localPoint = object.worldToLocal(intersectionPoint.clone());
|
|
34665
|
-
let snapPoint;
|
|
34666
|
-
let snapDistance = this.getDetectRadius(intersectionPoint);
|
|
34667
|
-
const geometry = object.geometry;
|
|
34668
|
-
const positions = geometry.attributes.position.array;
|
|
34669
|
-
for (let i = 0; i < positions.length; i += 3) {
|
|
34670
|
-
_vertex.set(positions[i], positions[i + 1], positions[i + 2]);
|
|
34671
|
-
const distance = _vertex.distanceTo(localPoint);
|
|
34672
|
-
if (distance < snapDistance) {
|
|
34673
|
-
snapDistance = distance;
|
|
34674
|
-
snapPoint = _vertex.clone();
|
|
34675
|
-
}
|
|
34676
|
-
}
|
|
34677
|
-
if (snapPoint)
|
|
34678
|
-
return object.localToWorld(snapPoint);
|
|
34679
|
-
let edges = this.edgesCache.get(geometry);
|
|
34680
|
-
if (!edges) {
|
|
34681
|
-
edges = new EdgesGeometry(geometry);
|
|
34682
|
-
this.edgesCache.set(geometry, edges);
|
|
34683
|
-
}
|
|
34684
|
-
const edgePositions = edges.attributes.position.array;
|
|
34685
|
-
for (let i = 0; i < edgePositions.length; i += 6) {
|
|
34686
|
-
_start$1.set(edgePositions[i], edgePositions[i + 1], edgePositions[i + 2]);
|
|
34687
|
-
_end$1.set(edgePositions[i + 3], edgePositions[i + 4], edgePositions[i + 5]);
|
|
34688
|
-
_line.set(_start$1, _end$1);
|
|
34689
|
-
_line.getCenter(_center);
|
|
34690
|
-
const centerDistance = _center.distanceTo(localPoint);
|
|
34691
|
-
if (centerDistance < snapDistance) {
|
|
34692
|
-
snapDistance = centerDistance;
|
|
34693
|
-
snapPoint = _center.clone();
|
|
34694
|
-
continue;
|
|
34695
|
-
}
|
|
34696
|
-
_line.closestPointToPoint(localPoint, true, _projection);
|
|
34697
|
-
const lineDistance = _projection.distanceTo(localPoint);
|
|
34698
|
-
if (lineDistance < snapDistance) {
|
|
34699
|
-
snapDistance = lineDistance;
|
|
34700
|
-
snapPoint = _projection.clone();
|
|
34701
|
-
}
|
|
34702
|
-
}
|
|
34703
|
-
if (snapPoint)
|
|
34704
|
-
return object.localToWorld(snapPoint);
|
|
34705
|
-
return intersectionPoint.clone();
|
|
34706
|
-
}
|
|
34707
|
-
}
|
|
34708
|
-
|
|
34709
34882
|
const _downPoint = new Vector2();
|
|
34710
34883
|
class MeasureLineDragger extends OrbitDragger {
|
|
34711
34884
|
constructor(viewer) {
|
|
@@ -35117,6 +35290,12 @@ void main() {
|
|
|
35117
35290
|
this.movementSpeed = 0.1;
|
|
35118
35291
|
this.multiplier = 3;
|
|
35119
35292
|
this.groundFollowingSkippedFrames = 0;
|
|
35293
|
+
this.GROUND_BOX_HALF_SIZE = 20;
|
|
35294
|
+
this.GROUND_BOX_REFRESH_THRESHOLD = 0.3;
|
|
35295
|
+
this._groundObjectBoxes = new Map();
|
|
35296
|
+
this._activeGroundObjects = [];
|
|
35297
|
+
this._groundBox = new Box3();
|
|
35298
|
+
this._groundBoxCenter = new Vector3();
|
|
35120
35299
|
this.moveWheel = 0;
|
|
35121
35300
|
this.mouseDragOn = false;
|
|
35122
35301
|
this._up = new Vector3();
|
|
@@ -35183,11 +35362,20 @@ void main() {
|
|
|
35183
35362
|
}
|
|
35184
35363
|
};
|
|
35185
35364
|
this.onKeyUp = (event) => {
|
|
35186
|
-
if (this.moveKeys.delete(event.code))
|
|
35365
|
+
if (this.moveKeys.delete(event.code)) {
|
|
35366
|
+
if (this.moveKeys.size === 0) {
|
|
35367
|
+
this._rebuildGroundBox(this.object.position);
|
|
35368
|
+
}
|
|
35187
35369
|
this.update();
|
|
35370
|
+
}
|
|
35188
35371
|
};
|
|
35189
35372
|
this.camera = camera;
|
|
35190
35373
|
this.groundObjects = groundObjects;
|
|
35374
|
+
for (const obj of groundObjects) {
|
|
35375
|
+
this._groundObjectBoxes.set(obj, new Box3().setFromObject(obj));
|
|
35376
|
+
}
|
|
35377
|
+
const pos = this.object.position;
|
|
35378
|
+
this._rebuildGroundBox(pos);
|
|
35191
35379
|
this.raycaster = new Raycaster();
|
|
35192
35380
|
this.raycaster.near = 0;
|
|
35193
35381
|
this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
|
|
@@ -35222,10 +35410,29 @@ void main() {
|
|
|
35222
35410
|
window.removeEventListener("keyup", this.onKeyUp);
|
|
35223
35411
|
super.dispose();
|
|
35224
35412
|
}
|
|
35413
|
+
_rebuildGroundBox(center) {
|
|
35414
|
+
const h = this.GROUND_BOX_HALF_SIZE;
|
|
35415
|
+
this._groundBoxCenter.copy(center);
|
|
35416
|
+
this._groundBox.set(new Vector3(center.x - h, center.y - h * 4, center.z - h), new Vector3(center.x + h, center.y + h * 4, center.z + h));
|
|
35417
|
+
this._activeGroundObjects = this.groundObjects.filter((obj) => {
|
|
35418
|
+
const objectBox = this._groundObjectBoxes.get(obj);
|
|
35419
|
+
return objectBox !== undefined && this._groundBox.intersectsBox(objectBox);
|
|
35420
|
+
});
|
|
35421
|
+
}
|
|
35422
|
+
_needsGroundBoxRebuild(pos) {
|
|
35423
|
+
if (this._activeGroundObjects.length === 0 && this.groundObjects.length > 0)
|
|
35424
|
+
return true;
|
|
35425
|
+
const threshold = this.GROUND_BOX_HALF_SIZE * this.GROUND_BOX_REFRESH_THRESHOLD;
|
|
35426
|
+
return (Math.abs(pos.x - this._groundBoxCenter.x) > threshold || Math.abs(pos.z - this._groundBoxCenter.z) > threshold);
|
|
35427
|
+
}
|
|
35225
35428
|
updateGroundFollowing() {
|
|
35429
|
+
const pos = this.object.position;
|
|
35430
|
+
if (this._needsGroundBoxRebuild(pos)) {
|
|
35431
|
+
this._rebuildGroundBox(pos);
|
|
35432
|
+
}
|
|
35226
35433
|
this._up.copy(this.camera.up).negate();
|
|
35227
|
-
this.raycaster.set(
|
|
35228
|
-
const intersects = this.raycaster.intersectObjects(this.
|
|
35434
|
+
this.raycaster.set(pos, this._up);
|
|
35435
|
+
const intersects = this.raycaster.intersectObjects(this._activeGroundObjects, false);
|
|
35229
35436
|
if (intersects.length > 0) {
|
|
35230
35437
|
const groundY = intersects[0].point.y;
|
|
35231
35438
|
const targetY = groundY + this.EYE_HEIGHT;
|
|
@@ -35777,6 +35984,7 @@ void main() {
|
|
|
35777
35984
|
draggers.registerDragger("Orbit", (viewer) => new OrbitDragger(viewer));
|
|
35778
35985
|
draggers.registerDragger("Zoom", (viewer) => new ZoomDragger(viewer));
|
|
35779
35986
|
draggers.registerDragger("MeasureLine", (viewer) => new MeasureLineDragger(viewer));
|
|
35987
|
+
draggers.registerDragger("CuttingPlane", (viewer) => new CuttingPlaneDragger(viewer));
|
|
35780
35988
|
draggers.registerDragger("CuttingPlaneXAxis", (viewer) => new CuttingPlaneXAxisDragger(viewer));
|
|
35781
35989
|
draggers.registerDragger("CuttingPlaneYAxis", (viewer) => new CuttingPlaneYAxisDragger(viewer));
|
|
35782
35990
|
draggers.registerDragger("CuttingPlaneZAxis", (viewer) => new CuttingPlaneZAxisDragger(viewer));
|
|
@@ -37311,7 +37519,7 @@ void main() {
|
|
|
37311
37519
|
this.getMousePosition(event, this.downPosition);
|
|
37312
37520
|
};
|
|
37313
37521
|
this.onPointerUp = (event) => {
|
|
37314
|
-
if (!event.isPrimary)
|
|
37522
|
+
if (!event.isPrimary || event.button !== 0)
|
|
37315
37523
|
return;
|
|
37316
37524
|
const upPosition = this.getMousePosition(event, new Vector2());
|
|
37317
37525
|
if (upPosition.distanceTo(this.downPosition) !== 0)
|
|
@@ -38774,6 +38982,81 @@ void main() {
|
|
|
38774
38982
|
this.mergedObjectMap = new Map();
|
|
38775
38983
|
this.mergedGeometryVisibility = new Map();
|
|
38776
38984
|
this._webglInfoCache = null;
|
|
38985
|
+
this.transformTextureSize = 1024;
|
|
38986
|
+
this.transformTexture = this.createDummyTexture();
|
|
38987
|
+
this.transformData = null;
|
|
38988
|
+
this.identityTransformData = null;
|
|
38989
|
+
this.visibilityMaterials = new Set();
|
|
38990
|
+
}
|
|
38991
|
+
createDummyTexture() {
|
|
38992
|
+
const data = new Float32Array(16);
|
|
38993
|
+
const identity = new Matrix4();
|
|
38994
|
+
identity.toArray(data);
|
|
38995
|
+
const dummyData = new Float32Array(16);
|
|
38996
|
+
identity.toArray(dummyData);
|
|
38997
|
+
const dummyTexture = new DataTexture(dummyData, 4, 1, RGBAFormat, FloatType);
|
|
38998
|
+
dummyTexture.minFilter = NearestFilter;
|
|
38999
|
+
dummyTexture.magFilter = NearestFilter;
|
|
39000
|
+
dummyTexture.needsUpdate = true;
|
|
39001
|
+
return dummyTexture;
|
|
39002
|
+
}
|
|
39003
|
+
initTransformTexture() {
|
|
39004
|
+
if (this.transformTexture) {
|
|
39005
|
+
this.transformTexture.dispose();
|
|
39006
|
+
}
|
|
39007
|
+
const maxInstanceCount = this.maxObjectId + 1;
|
|
39008
|
+
let size = Math.sqrt(maxInstanceCount * 4);
|
|
39009
|
+
size = Math.ceil(size / 4) * 4;
|
|
39010
|
+
size = Math.max(size, 4);
|
|
39011
|
+
this.transformTextureSize = size;
|
|
39012
|
+
const arraySize = size * size * 4;
|
|
39013
|
+
this.transformData = new Float32Array(arraySize);
|
|
39014
|
+
this.identityTransformData = new Float32Array(arraySize);
|
|
39015
|
+
for (let i = 0; i <= this.maxObjectId; i++) {
|
|
39016
|
+
const base = i * 16;
|
|
39017
|
+
if (base + 15 < arraySize) {
|
|
39018
|
+
this.identityTransformData[base + 0] = 1;
|
|
39019
|
+
this.identityTransformData[base + 5] = 1;
|
|
39020
|
+
this.identityTransformData[base + 10] = 1;
|
|
39021
|
+
this.identityTransformData[base + 15] = 1;
|
|
39022
|
+
}
|
|
39023
|
+
}
|
|
39024
|
+
this._resetTransformData(false);
|
|
39025
|
+
this.transformTexture = new DataTexture(this.transformData, size, size, RGBAFormat, FloatType);
|
|
39026
|
+
this.transformTexture.needsUpdate = true;
|
|
39027
|
+
this.transformTexture.generateMipmaps = false;
|
|
39028
|
+
console.log(`Initialized transform texture: ${size}x${size} for ${maxInstanceCount} objects`);
|
|
39029
|
+
this.updateMaterialUniforms();
|
|
39030
|
+
this.visibilityMaterials.forEach((material) => {
|
|
39031
|
+
material.needsUpdate = true;
|
|
39032
|
+
});
|
|
39033
|
+
}
|
|
39034
|
+
_resetTransformData(updateTexture = true) {
|
|
39035
|
+
if (!this.transformData || !this.identityTransformData) return;
|
|
39036
|
+
this.transformData.set(this.identityTransformData);
|
|
39037
|
+
if (updateTexture) {
|
|
39038
|
+
this.updateTransformTexture();
|
|
39039
|
+
}
|
|
39040
|
+
}
|
|
39041
|
+
updateMaterialUniforms() {
|
|
39042
|
+
if (
|
|
39043
|
+
this._lastTransformTexture === this.transformTexture &&
|
|
39044
|
+
this._lastTransformTextureSize === this.transformTextureSize
|
|
39045
|
+
) {
|
|
39046
|
+
return;
|
|
39047
|
+
}
|
|
39048
|
+
this._lastTransformTexture = this.transformTexture;
|
|
39049
|
+
this._lastTransformTextureSize = this.transformTextureSize;
|
|
39050
|
+
this.visibilityMaterials.forEach((material) => {
|
|
39051
|
+
if (material.userData && material.userData.visibilityUniforms) {
|
|
39052
|
+
material.userData.visibilityUniforms.transformTexture.value = this.transformTexture;
|
|
39053
|
+
material.userData.visibilityUniforms.transformTextureSize.value = this.transformTextureSize;
|
|
39054
|
+
}
|
|
39055
|
+
});
|
|
39056
|
+
}
|
|
39057
|
+
updateTransformTexture() {
|
|
39058
|
+
if (!this.transformTexture) return;
|
|
39059
|
+
this.transformTexture.needsUpdate = true;
|
|
38777
39060
|
}
|
|
38778
39061
|
setVisibleEdges(visible) {
|
|
38779
39062
|
this.visibleEdges = visible;
|
|
@@ -39663,36 +39946,82 @@ void main() {
|
|
|
39663
39946
|
}
|
|
39664
39947
|
}
|
|
39665
39948
|
createVisibilityMaterial(material) {
|
|
39949
|
+
this.visibilityMaterials.add(material);
|
|
39950
|
+
const uniforms = {
|
|
39951
|
+
transformTexture: { value: this.transformTexture },
|
|
39952
|
+
transformTextureSize: { value: this.transformTextureSize },
|
|
39953
|
+
};
|
|
39954
|
+
material.userData.visibilityUniforms = uniforms;
|
|
39666
39955
|
material.onBeforeCompile = (shader) => {
|
|
39956
|
+
shader.uniforms.transformTexture = uniforms.transformTexture;
|
|
39957
|
+
shader.uniforms.transformTextureSize = uniforms.transformTextureSize;
|
|
39667
39958
|
shader.vertexShader = shader.vertexShader.replace(
|
|
39668
39959
|
"#include <common>",
|
|
39669
39960
|
`
|
|
39670
39961
|
#include <common>
|
|
39962
|
+
|
|
39671
39963
|
attribute float visibility;
|
|
39964
|
+
attribute float objectId;
|
|
39672
39965
|
varying float vVisibility;
|
|
39673
|
-
|
|
39674
|
-
|
|
39675
|
-
|
|
39676
|
-
|
|
39677
|
-
|
|
39678
|
-
|
|
39679
|
-
|
|
39966
|
+
uniform highp sampler2D transformTexture;
|
|
39967
|
+
uniform float transformTextureSize;
|
|
39968
|
+
|
|
39969
|
+
mat4 getTransformMatrix(float instanceId) {
|
|
39970
|
+
int size = int(transformTextureSize);
|
|
39971
|
+
int index = int(instanceId) * 4;
|
|
39972
|
+
|
|
39973
|
+
int x0 = index % size;
|
|
39974
|
+
int y0 = index / size;
|
|
39975
|
+
|
|
39976
|
+
vec4 row0 = texelFetch(transformTexture, ivec2(x0, y0), 0);
|
|
39977
|
+
vec4 row1 = texelFetch(transformTexture, ivec2(x0 + 1, y0), 0);
|
|
39978
|
+
vec4 row2 = texelFetch(transformTexture, ivec2(x0 + 2, y0), 0);
|
|
39979
|
+
vec4 row3 = texelFetch(transformTexture, ivec2(x0 + 3, y0), 0);
|
|
39980
|
+
|
|
39981
|
+
return mat4(row0, row1, row2, row3);
|
|
39982
|
+
}
|
|
39680
39983
|
`
|
|
39681
39984
|
);
|
|
39682
39985
|
shader.vertexShader = shader.vertexShader.replace(
|
|
39683
39986
|
"void main() {",
|
|
39684
39987
|
`
|
|
39685
39988
|
void main() {
|
|
39686
|
-
|
|
39989
|
+
mat4 batchingMatrix = getTransformMatrix(objectId);
|
|
39990
|
+
vVisibility = visibility;
|
|
39687
39991
|
`
|
|
39688
39992
|
);
|
|
39689
|
-
|
|
39690
|
-
|
|
39993
|
+
if (shader.vertexShader.includes("#include <beginnormal_vertex>")) {
|
|
39994
|
+
shader.vertexShader = shader.vertexShader.replace(
|
|
39995
|
+
"#include <beginnormal_vertex>",
|
|
39996
|
+
`
|
|
39997
|
+
vec3 objectNormal = vec3( normal );
|
|
39998
|
+
mat3 bm = mat3( batchingMatrix );
|
|
39999
|
+
objectNormal = bm * objectNormal;
|
|
39691
40000
|
`
|
|
40001
|
+
);
|
|
40002
|
+
}
|
|
40003
|
+
shader.vertexShader = shader.vertexShader.replace(
|
|
40004
|
+
"#include <begin_vertex>",
|
|
40005
|
+
`
|
|
40006
|
+
vec3 transformed = vec3( position );
|
|
40007
|
+
transformed = ( batchingMatrix * vec4( transformed, 1.0 ) ).xyz;
|
|
40008
|
+
`
|
|
40009
|
+
);
|
|
40010
|
+
shader.fragmentShader = shader.fragmentShader
|
|
40011
|
+
.replace(
|
|
40012
|
+
"#include <common>",
|
|
40013
|
+
`
|
|
40014
|
+
#include <common>
|
|
40015
|
+
varying float vVisibility;
|
|
40016
|
+
`
|
|
40017
|
+
)
|
|
40018
|
+
.replace(
|
|
40019
|
+
"void main() {",
|
|
40020
|
+
`
|
|
39692
40021
|
void main() {
|
|
39693
40022
|
if (vVisibility < 0.5) discard;
|
|
39694
40023
|
`
|
|
39695
|
-
|
|
40024
|
+
);
|
|
39696
40025
|
};
|
|
39697
40026
|
material.needsUpdate = true;
|
|
39698
40027
|
return material;
|
|
@@ -39807,6 +40136,8 @@ void main() {
|
|
|
39807
40136
|
this.objectIdToIndex.clear();
|
|
39808
40137
|
this.maxObjectId = 0;
|
|
39809
40138
|
this.objectVisibility = new Float32Array();
|
|
40139
|
+
this.meshToNodeMap = null;
|
|
40140
|
+
this.visibilityMaterials.clear();
|
|
39810
40141
|
}
|
|
39811
40142
|
setStructureTransform(structureId, matrix) {
|
|
39812
40143
|
const rootGroup = this.structureRoots.get(structureId);
|
|
@@ -39922,12 +40253,15 @@ void main() {
|
|
|
39922
40253
|
});
|
|
39923
40254
|
this.originalObjects.clear();
|
|
39924
40255
|
this.originalObjectsToSelection.clear();
|
|
40256
|
+
this.objectIdToIndex.clear();
|
|
40257
|
+
this.maxObjectId = 0;
|
|
39925
40258
|
const structureGroups = new Map();
|
|
39926
40259
|
this.dispatchEvent("optimizationprogress", {
|
|
39927
40260
|
phase: "collecting",
|
|
39928
40261
|
progress: 5,
|
|
39929
40262
|
message: "Collecting scene objects...",
|
|
39930
40263
|
});
|
|
40264
|
+
let totalObjectsToMerge = 0;
|
|
39931
40265
|
this.scene.traverse((object) => {
|
|
39932
40266
|
if (object.userData.structureId) {
|
|
39933
40267
|
const structureId = object.userData.structureId;
|
|
@@ -39945,17 +40279,32 @@ void main() {
|
|
|
39945
40279
|
});
|
|
39946
40280
|
}
|
|
39947
40281
|
const group = structureGroups.get(structureId);
|
|
40282
|
+
let added = false;
|
|
39948
40283
|
if (object instanceof Mesh) {
|
|
39949
40284
|
this.addToMaterialGroup(object, group.mapMeshes, group.meshes);
|
|
40285
|
+
added = true;
|
|
39950
40286
|
} else if (object instanceof LineSegments) {
|
|
39951
40287
|
this.addToMaterialGroup(object, group.mapLineSegments, group.lineSegments);
|
|
40288
|
+
added = true;
|
|
39952
40289
|
} else if (object instanceof Line$1) {
|
|
39953
40290
|
this.addToMaterialGroup(object, group.mapLines, group.lines);
|
|
40291
|
+
added = true;
|
|
39954
40292
|
} else if (object instanceof Points) {
|
|
39955
40293
|
this.addToMaterialGroup(object, group.mapPoints, group.points);
|
|
40294
|
+
added = true;
|
|
40295
|
+
}
|
|
40296
|
+
if (added) {
|
|
40297
|
+
totalObjectsToMerge++;
|
|
39956
40298
|
}
|
|
39957
40299
|
}
|
|
39958
40300
|
});
|
|
40301
|
+
if (totalObjectsToMerge > 0) {
|
|
40302
|
+
console.log(`Pre-allocating transform texture for ${totalObjectsToMerge} objects`);
|
|
40303
|
+
this.maxObjectId = totalObjectsToMerge;
|
|
40304
|
+
this.initTransformTexture();
|
|
40305
|
+
this.initializeObjectVisibility();
|
|
40306
|
+
this.maxObjectId = 0;
|
|
40307
|
+
}
|
|
39959
40308
|
let processedGroups = 0;
|
|
39960
40309
|
const totalGroups = structureGroups.size;
|
|
39961
40310
|
this.dispatchEvent("optimizationprogress", {
|
|
@@ -40000,7 +40349,6 @@ void main() {
|
|
|
40000
40349
|
this.originalObjectsToSelection.add(obj);
|
|
40001
40350
|
}
|
|
40002
40351
|
});
|
|
40003
|
-
this.initializeObjectVisibility();
|
|
40004
40352
|
console.log(`Optimization complete. Total objects: ${this.maxObjectId}`);
|
|
40005
40353
|
this.dispatchEvent("optimizationprogress", {
|
|
40006
40354
|
phase: "complete",
|
|
@@ -40069,6 +40417,7 @@ void main() {
|
|
|
40069
40417
|
}
|
|
40070
40418
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40071
40419
|
const mergedMesh = new Mesh(mergedGeometry, visibilityMaterial);
|
|
40420
|
+
mergedMesh.frustumCulled = false;
|
|
40072
40421
|
mergedMesh.userData.isOptimized = true;
|
|
40073
40422
|
rootGroup.add(mergedMesh);
|
|
40074
40423
|
this.mergedMesh.add(mergedMesh);
|
|
@@ -40185,6 +40534,7 @@ void main() {
|
|
|
40185
40534
|
geometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40186
40535
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40187
40536
|
const mergedLine = new LineSegments(geometry, visibilityMaterial);
|
|
40537
|
+
mergedLine.frustumCulled = false;
|
|
40188
40538
|
mergedLine.userData.isEdge = isEdge;
|
|
40189
40539
|
mergedLine.userData.isOptimized = true;
|
|
40190
40540
|
const mergedObjects = [mergedLine];
|
|
@@ -40273,6 +40623,7 @@ void main() {
|
|
|
40273
40623
|
mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40274
40624
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40275
40625
|
const mergedLine = new LineSegments(mergedGeometry, visibilityMaterial);
|
|
40626
|
+
mergedLine.frustumCulled = false;
|
|
40276
40627
|
mergedLine.userData.isEdge = isEdge;
|
|
40277
40628
|
mergedLine.userData.isOptimized = true;
|
|
40278
40629
|
if (this.useVAO) {
|
|
@@ -40342,7 +40693,27 @@ void main() {
|
|
|
40342
40693
|
const mergedObjects = [];
|
|
40343
40694
|
if (geometries.length > 0) {
|
|
40344
40695
|
const mergedGeometry = mergeGeometries(geometries, false);
|
|
40345
|
-
const
|
|
40696
|
+
const totalVertices = mergedGeometry.attributes.position.count;
|
|
40697
|
+
const objectIds = new Float32Array(totalVertices);
|
|
40698
|
+
let vertexOffset = 0;
|
|
40699
|
+
group.objects.forEach((points) => {
|
|
40700
|
+
const handle = points.userData.handle;
|
|
40701
|
+
if (!this.objectIdToIndex.has(handle)) {
|
|
40702
|
+
this.objectIdToIndex.set(handle, this.maxObjectId++);
|
|
40703
|
+
}
|
|
40704
|
+
const objectId = this.objectIdToIndex.get(handle);
|
|
40705
|
+
const count = points.geometry.attributes.position.count;
|
|
40706
|
+
for (let i = 0; i < count; i++) {
|
|
40707
|
+
objectIds[vertexOffset++] = objectId;
|
|
40708
|
+
}
|
|
40709
|
+
});
|
|
40710
|
+
mergedGeometry.setAttribute("objectId", new BufferAttribute(objectIds, 1));
|
|
40711
|
+
const visibilityArray = new Float32Array(totalVertices);
|
|
40712
|
+
visibilityArray.fill(1.0);
|
|
40713
|
+
mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40714
|
+
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40715
|
+
const mergedPoints = new Points(mergedGeometry, visibilityMaterial);
|
|
40716
|
+
mergedPoints.frustumCulled = false;
|
|
40346
40717
|
mergedPoints.userData.isOptimized = true;
|
|
40347
40718
|
if (this.useVAO) {
|
|
40348
40719
|
this.createVAO(mergedPoints);
|
|
@@ -40411,13 +40782,33 @@ void main() {
|
|
|
40411
40782
|
geometriesWithIndex.push(clonedGeometry);
|
|
40412
40783
|
});
|
|
40413
40784
|
const finalGeometry = mergeGeometries(geometriesWithIndex, false);
|
|
40785
|
+
const totalVertices = finalGeometry.attributes.position.count;
|
|
40786
|
+
const objectIds = new Float32Array(totalVertices);
|
|
40787
|
+
let vertexOffset = 0;
|
|
40788
|
+
lineSegmentsArray.forEach((segment) => {
|
|
40789
|
+
const handle = segment.userData.handle;
|
|
40790
|
+
if (!this.objectIdToIndex.has(handle)) {
|
|
40791
|
+
this.objectIdToIndex.set(handle, this.maxObjectId++);
|
|
40792
|
+
}
|
|
40793
|
+
const objectId = this.objectIdToIndex.get(handle);
|
|
40794
|
+
const count = segment.geometry.attributes.position.count;
|
|
40795
|
+
for (let i = 0; i < count; i++) {
|
|
40796
|
+
objectIds[vertexOffset++] = objectId;
|
|
40797
|
+
}
|
|
40798
|
+
});
|
|
40799
|
+
finalGeometry.setAttribute("objectId", new BufferAttribute(objectIds, 1));
|
|
40800
|
+
const visibilityArray = new Float32Array(totalVertices);
|
|
40801
|
+
visibilityArray.fill(1.0);
|
|
40802
|
+
finalGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40414
40803
|
const material = new LineBasicMaterial({
|
|
40415
40804
|
vertexColors: true,
|
|
40416
40805
|
});
|
|
40806
|
+
const visibilityMaterial = this.createVisibilityMaterial(material);
|
|
40417
40807
|
if (this.useVAO) {
|
|
40418
40808
|
this.createVAO(finalGeometry);
|
|
40419
40809
|
}
|
|
40420
|
-
const mergedLine = new LineSegments(finalGeometry,
|
|
40810
|
+
const mergedLine = new LineSegments(finalGeometry, visibilityMaterial);
|
|
40811
|
+
mergedLine.frustumCulled = false;
|
|
40421
40812
|
mergedLine.userData.structureId = structureId;
|
|
40422
40813
|
mergedLine.userData.isOptimized = true;
|
|
40423
40814
|
rootGroup.add(mergedLine);
|
|
@@ -40536,18 +40927,50 @@ void main() {
|
|
|
40536
40927
|
console.warn("No merged objects to transform");
|
|
40537
40928
|
return;
|
|
40538
40929
|
}
|
|
40539
|
-
this.
|
|
40540
|
-
|
|
40541
|
-
|
|
40542
|
-
}
|
|
40543
|
-
for (const line of this.mergedLines) {
|
|
40544
|
-
this._applyTransformToMergedObject(line);
|
|
40930
|
+
if (!this.transformData) {
|
|
40931
|
+
console.warn("Transform texture not initialized");
|
|
40932
|
+
return;
|
|
40545
40933
|
}
|
|
40546
|
-
|
|
40547
|
-
|
|
40934
|
+
this.objectTransforms = objectTransformMap;
|
|
40935
|
+
this._resetTransformData(false);
|
|
40936
|
+
const transformData = this.transformData;
|
|
40937
|
+
const objectIdToIndex = this.objectIdToIndex;
|
|
40938
|
+
let textureNeedsUpdate = false;
|
|
40939
|
+
if (objectTransformMap instanceof Map) {
|
|
40940
|
+
for (const [object, matrix] of objectTransformMap.entries()) {
|
|
40941
|
+
const userData = object.userData;
|
|
40942
|
+
if (!userData) continue;
|
|
40943
|
+
const handle = userData.handle;
|
|
40944
|
+
if (handle === undefined) continue;
|
|
40945
|
+
const objectId = objectIdToIndex.get(handle);
|
|
40946
|
+
if (objectId !== undefined) {
|
|
40947
|
+
transformData.set(matrix.elements, objectId * 16);
|
|
40948
|
+
textureNeedsUpdate = true;
|
|
40949
|
+
}
|
|
40950
|
+
}
|
|
40951
|
+
} else {
|
|
40952
|
+
const len = objectTransformMap.length;
|
|
40953
|
+
for (let i = 0; i < len; i++) {
|
|
40954
|
+
const pair = objectTransformMap[i];
|
|
40955
|
+
const userData = pair[0].userData;
|
|
40956
|
+
if (!userData) continue;
|
|
40957
|
+
const handle = userData.handle;
|
|
40958
|
+
if (handle === undefined) continue;
|
|
40959
|
+
const objectId = objectIdToIndex.get(handle);
|
|
40960
|
+
if (objectId !== undefined) {
|
|
40961
|
+
transformData.set(pair[1].elements, objectId * 16);
|
|
40962
|
+
textureNeedsUpdate = true;
|
|
40963
|
+
}
|
|
40964
|
+
}
|
|
40548
40965
|
}
|
|
40549
|
-
|
|
40550
|
-
this.
|
|
40966
|
+
if (textureNeedsUpdate) {
|
|
40967
|
+
this.updateTransformTexture();
|
|
40968
|
+
if (
|
|
40969
|
+
this._lastTransformTexture !== this.transformTexture ||
|
|
40970
|
+
this._lastTransformTextureSize !== this.transformTextureSize
|
|
40971
|
+
) {
|
|
40972
|
+
this.updateMaterialUniforms();
|
|
40973
|
+
}
|
|
40551
40974
|
}
|
|
40552
40975
|
}
|
|
40553
40976
|
createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
|
|
@@ -40564,21 +40987,66 @@ void main() {
|
|
|
40564
40987
|
? objects
|
|
40565
40988
|
: Array.from(objects)
|
|
40566
40989
|
: Array.from(this.originalObjects);
|
|
40990
|
+
const structureInverseMatrices = new Map();
|
|
40991
|
+
if (!this.meshToNodeMap) {
|
|
40992
|
+
this.meshToNodeMap = new Map();
|
|
40993
|
+
for (const node of this.nodes.values()) {
|
|
40994
|
+
if (node.object) {
|
|
40995
|
+
this.meshToNodeMap.set(node.object, node);
|
|
40996
|
+
}
|
|
40997
|
+
}
|
|
40998
|
+
}
|
|
40567
40999
|
for (const obj of objectsArray) {
|
|
40568
41000
|
if (!obj.geometry || !obj.geometry.attributes.position) continue;
|
|
40569
|
-
|
|
40570
|
-
|
|
40571
|
-
|
|
41001
|
+
if (!obj.userData.explodeVector) {
|
|
41002
|
+
let center = null;
|
|
41003
|
+
const node = this.meshToNodeMap.get(obj);
|
|
41004
|
+
if (node && node.geometryExtents) {
|
|
41005
|
+
const box = node.geometryExtents.clone();
|
|
41006
|
+
box.applyMatrix4(obj.matrixWorld);
|
|
41007
|
+
center = new Vector3();
|
|
41008
|
+
box.getCenter(center);
|
|
41009
|
+
}
|
|
41010
|
+
if (!center) {
|
|
41011
|
+
if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
|
|
41012
|
+
const box = obj.geometry.boundingBox.clone();
|
|
41013
|
+
box.applyMatrix4(obj.matrixWorld);
|
|
41014
|
+
center = new Vector3();
|
|
41015
|
+
box.getCenter(center);
|
|
41016
|
+
}
|
|
41017
|
+
const explodeVector = center.sub(explodeCenter);
|
|
41018
|
+
obj.userData.explodeVector = explodeVector;
|
|
40572
41019
|
}
|
|
40573
|
-
|
|
40574
|
-
const
|
|
40575
|
-
boundingBox.getCenter(objectCenter);
|
|
40576
|
-
const direction = objectCenter.clone().sub(explodeCenter);
|
|
40577
|
-
const distance = direction.length();
|
|
41020
|
+
const explodeVector = obj.userData.explodeVector;
|
|
41021
|
+
const distance = explodeVector.length();
|
|
40578
41022
|
if (distance > 0) {
|
|
40579
|
-
|
|
40580
|
-
const
|
|
40581
|
-
|
|
41023
|
+
const offset = explodeVector.clone().multiplyScalar(explodeFactor - 1.0);
|
|
41024
|
+
const localOffset = offset.clone();
|
|
41025
|
+
if (obj.userData.structureId) {
|
|
41026
|
+
const structureId = obj.userData.structureId;
|
|
41027
|
+
let inverseMatrix = structureInverseMatrices.get(structureId);
|
|
41028
|
+
if (!inverseMatrix) {
|
|
41029
|
+
const rootGroup = this.structureRoots.get(structureId);
|
|
41030
|
+
if (rootGroup) {
|
|
41031
|
+
if (!rootGroup.userData.inverseWorldMatrix) {
|
|
41032
|
+
rootGroup.userData.inverseWorldMatrix = new Matrix4().copy(rootGroup.matrixWorld).invert();
|
|
41033
|
+
}
|
|
41034
|
+
inverseMatrix = rootGroup.userData.inverseWorldMatrix;
|
|
41035
|
+
structureInverseMatrices.set(structureId, inverseMatrix);
|
|
41036
|
+
}
|
|
41037
|
+
}
|
|
41038
|
+
if (inverseMatrix) {
|
|
41039
|
+
const zero = new Vector3(0, 0, 0).applyMatrix4(inverseMatrix);
|
|
41040
|
+
const vec = offset.clone().applyMatrix4(inverseMatrix).sub(zero);
|
|
41041
|
+
localOffset.copy(vec);
|
|
41042
|
+
}
|
|
41043
|
+
}
|
|
41044
|
+
let matrix = obj.userData.explodeMatrix;
|
|
41045
|
+
if (!matrix) {
|
|
41046
|
+
matrix = new Matrix4();
|
|
41047
|
+
obj.userData.explodeMatrix = matrix;
|
|
41048
|
+
}
|
|
41049
|
+
matrix.makeTranslation(localOffset.x, localOffset.y, localOffset.z);
|
|
40582
41050
|
transformMap.set(obj, matrix);
|
|
40583
41051
|
}
|
|
40584
41052
|
}
|
|
@@ -40586,116 +41054,11 @@ void main() {
|
|
|
40586
41054
|
}
|
|
40587
41055
|
clearTransforms() {
|
|
40588
41056
|
this.objectTransforms.clear();
|
|
40589
|
-
|
|
40590
|
-
this._restoreOriginalGeometry(mesh);
|
|
40591
|
-
}
|
|
40592
|
-
for (const line of this.mergedLines) {
|
|
40593
|
-
this._restoreOriginalGeometry(line);
|
|
40594
|
-
}
|
|
40595
|
-
for (const lineSegment of this.mergedLineSegments) {
|
|
40596
|
-
this._restoreOriginalGeometry(lineSegment);
|
|
40597
|
-
}
|
|
40598
|
-
for (const point of this.mergedPoints) {
|
|
40599
|
-
this._restoreOriginalGeometry(point);
|
|
40600
|
-
}
|
|
41057
|
+
this._resetTransformData(true);
|
|
40601
41058
|
}
|
|
40602
41059
|
clearHandleTransforms() {
|
|
40603
41060
|
this.clearTransforms();
|
|
40604
41061
|
}
|
|
40605
|
-
_applyTransformToMergedObject(mergedObject) {
|
|
40606
|
-
const objectData = this.mergedObjectMap.get(mergedObject.uuid);
|
|
40607
|
-
if (!objectData || !objectData.objectMapping) return;
|
|
40608
|
-
const geometry = mergedObject.geometry;
|
|
40609
|
-
if (!geometry || !geometry.attributes.position) return;
|
|
40610
|
-
const positionAttr = geometry.attributes.position;
|
|
40611
|
-
const positions = positionAttr.array;
|
|
40612
|
-
if (!this.transformedGeometries.has(mergedObject.uuid)) {
|
|
40613
|
-
this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
|
|
40614
|
-
}
|
|
40615
|
-
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
40616
|
-
const tempVector = new Vector3();
|
|
40617
|
-
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
40618
|
-
const transform = this.objectTransforms.get(originalMesh);
|
|
40619
|
-
if (!transform) {
|
|
40620
|
-
const startIdx = mappingData.startVertexIndex * 3;
|
|
40621
|
-
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
40622
|
-
for (let i = startIdx; i < endIdx; i++) {
|
|
40623
|
-
positions[i] = originalPositions[i];
|
|
40624
|
-
}
|
|
40625
|
-
continue;
|
|
40626
|
-
}
|
|
40627
|
-
const startVertex = mappingData.startVertexIndex;
|
|
40628
|
-
const vertexCount = mappingData.vertexCount;
|
|
40629
|
-
for (let i = 0; i < vertexCount; i++) {
|
|
40630
|
-
const idx = (startVertex + i) * 3;
|
|
40631
|
-
tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
|
|
40632
|
-
tempVector.applyMatrix4(transform);
|
|
40633
|
-
positions[idx] = tempVector.x;
|
|
40634
|
-
positions[idx + 1] = tempVector.y;
|
|
40635
|
-
positions[idx + 2] = tempVector.z;
|
|
40636
|
-
}
|
|
40637
|
-
}
|
|
40638
|
-
if (geometry.attributes.normal) {
|
|
40639
|
-
this._updateNormalsForTransform(geometry, objectData, originalPositions);
|
|
40640
|
-
}
|
|
40641
|
-
positionAttr.needsUpdate = true;
|
|
40642
|
-
geometry.computeBoundingSphere();
|
|
40643
|
-
geometry.computeBoundingBox();
|
|
40644
|
-
}
|
|
40645
|
-
_updateNormalsForTransform(geometry, objectData, originalPositions) {
|
|
40646
|
-
const normalAttr = geometry.attributes.normal;
|
|
40647
|
-
if (!normalAttr) return;
|
|
40648
|
-
const normals = normalAttr.array;
|
|
40649
|
-
const tempVector = new Vector3();
|
|
40650
|
-
const normalMatrix = new Matrix4();
|
|
40651
|
-
const normalsKey = `${geometry.uuid}_normals`;
|
|
40652
|
-
if (!this.transformedGeometries.has(normalsKey)) {
|
|
40653
|
-
this.transformedGeometries.set(normalsKey, new Float32Array(normals));
|
|
40654
|
-
}
|
|
40655
|
-
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
40656
|
-
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
40657
|
-
const transform = this.objectTransforms.get(originalMesh);
|
|
40658
|
-
if (!transform) {
|
|
40659
|
-
const startIdx = mappingData.startVertexIndex * 3;
|
|
40660
|
-
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
40661
|
-
for (let i = startIdx; i < endIdx; i++) {
|
|
40662
|
-
normals[i] = originalNormals[i];
|
|
40663
|
-
}
|
|
40664
|
-
continue;
|
|
40665
|
-
}
|
|
40666
|
-
normalMatrix.copy(transform).invert().transpose();
|
|
40667
|
-
const startVertex = mappingData.startVertexIndex;
|
|
40668
|
-
const vertexCount = mappingData.vertexCount;
|
|
40669
|
-
for (let i = 0; i < vertexCount; i++) {
|
|
40670
|
-
const idx = (startVertex + i) * 3;
|
|
40671
|
-
tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
|
|
40672
|
-
tempVector.applyMatrix4(normalMatrix).normalize();
|
|
40673
|
-
normals[idx] = tempVector.x;
|
|
40674
|
-
normals[idx + 1] = tempVector.y;
|
|
40675
|
-
normals[idx + 2] = tempVector.z;
|
|
40676
|
-
}
|
|
40677
|
-
}
|
|
40678
|
-
normalAttr.needsUpdate = true;
|
|
40679
|
-
}
|
|
40680
|
-
_restoreOriginalGeometry(mergedObject) {
|
|
40681
|
-
const geometry = mergedObject.geometry;
|
|
40682
|
-
if (!geometry || !geometry.attributes.position) return;
|
|
40683
|
-
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
40684
|
-
if (originalPositions) {
|
|
40685
|
-
const positions = geometry.attributes.position.array;
|
|
40686
|
-
positions.set(originalPositions);
|
|
40687
|
-
geometry.attributes.position.needsUpdate = true;
|
|
40688
|
-
}
|
|
40689
|
-
const normalsKey = `${geometry.uuid}_normals`;
|
|
40690
|
-
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
40691
|
-
if (originalNormals && geometry.attributes.normal) {
|
|
40692
|
-
const normals = geometry.attributes.normal.array;
|
|
40693
|
-
normals.set(originalNormals);
|
|
40694
|
-
geometry.attributes.normal.needsUpdate = true;
|
|
40695
|
-
}
|
|
40696
|
-
geometry.computeBoundingSphere();
|
|
40697
|
-
geometry.computeBoundingBox();
|
|
40698
|
-
}
|
|
40699
41062
|
syncHiddenObjects() {
|
|
40700
41063
|
if (this.mergedObjectMap.size === 0) {
|
|
40701
41064
|
console.log("No merged objects to sync");
|
|
@@ -57746,12 +58109,14 @@ js: import "konva/skia-backend";
|
|
|
57746
58109
|
if (!this.renderer)
|
|
57747
58110
|
return;
|
|
57748
58111
|
this._markup.clearOverlay();
|
|
58112
|
+
this.emitEvent({ type: "clearoverlay" });
|
|
57749
58113
|
this.update();
|
|
57750
58114
|
}
|
|
57751
58115
|
clearSlices() {
|
|
57752
58116
|
if (!this.renderer)
|
|
57753
58117
|
return;
|
|
57754
58118
|
this.renderer.clippingPlanes = [];
|
|
58119
|
+
this.emitEvent({ type: "clearslices" });
|
|
57755
58120
|
this.update();
|
|
57756
58121
|
}
|
|
57757
58122
|
getSelected() {
|