@inweb/viewer-three 27.2.3 → 27.2.4
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 +319 -652
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +321 -654
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/controls/WalkControls.d.ts +0 -8
- package/lib/Viewer/draggers/CuttingPlaneDragger.d.ts +5 -23
- package/lib/Viewer/helpers/PlaneHelper2.d.ts +4 -8
- package/lib/Viewer/measurement/Snapper.d.ts +1 -1
- package/package.json +5 -5
- package/src/Viewer/components/SelectionComponent.ts +1 -1
- package/src/Viewer/controls/WalkControls.ts +4 -50
- package/src/Viewer/draggers/CuttingPlaneDragger.ts +31 -191
- package/src/Viewer/draggers/CuttingPlaneXAxis.ts +3 -2
- package/src/Viewer/draggers/CuttingPlaneYAxis.ts +3 -2
- package/src/Viewer/draggers/CuttingPlaneZAxis.ts +3 -2
- package/src/Viewer/draggers/index.ts +0 -2
- package/src/Viewer/helpers/PlaneHelper2.ts +17 -30
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +189 -413
- package/src/Viewer/measurement/Snapper.ts +5 -13
package/dist/viewer-three.js
CHANGED
|
@@ -33644,6 +33644,41 @@ void main() {
|
|
|
33644
33644
|
}
|
|
33645
33645
|
}
|
|
33646
33646
|
|
|
33647
|
+
class PlaneHelper2 extends Line$1 {
|
|
33648
|
+
constructor(size = 1, color = 0xc0c0c0) {
|
|
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 = "PlaneHelper2";
|
|
33655
|
+
this.size = size;
|
|
33656
|
+
const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
|
|
33657
|
+
const geometry2 = new BufferGeometry();
|
|
33658
|
+
geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
|
|
33659
|
+
geometry2.computeBoundingSphere();
|
|
33660
|
+
this.helper = new Mesh(geometry2, new MeshBasicMaterial({
|
|
33661
|
+
color,
|
|
33662
|
+
opacity: 0.2,
|
|
33663
|
+
transparent: true,
|
|
33664
|
+
depthWrite: false,
|
|
33665
|
+
toneMapped: false,
|
|
33666
|
+
side: DoubleSide,
|
|
33667
|
+
}));
|
|
33668
|
+
this.add(this.helper);
|
|
33669
|
+
}
|
|
33670
|
+
dispose() {
|
|
33671
|
+
this.geometry.dispose();
|
|
33672
|
+
this.material.dispose();
|
|
33673
|
+
this.helper.geometry.dispose();
|
|
33674
|
+
this.helper.material.dispose();
|
|
33675
|
+
}
|
|
33676
|
+
updateMatrixWorld(force) {
|
|
33677
|
+
this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
|
|
33678
|
+
super.updateMatrixWorld(force);
|
|
33679
|
+
}
|
|
33680
|
+
}
|
|
33681
|
+
|
|
33647
33682
|
const _changeEvent = { type: "change" };
|
|
33648
33683
|
const _startEvent = { type: "start" };
|
|
33649
33684
|
const _endEvent = { type: "end" };
|
|
@@ -34302,166 +34337,6 @@ void main() {
|
|
|
34302
34337
|
}
|
|
34303
34338
|
}
|
|
34304
34339
|
|
|
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
|
-
|
|
34465
34340
|
class OrbitDragger {
|
|
34466
34341
|
constructor(viewer) {
|
|
34467
34342
|
this.updateControls = () => {
|
|
@@ -34554,18 +34429,12 @@ void main() {
|
|
|
34554
34429
|
}
|
|
34555
34430
|
|
|
34556
34431
|
class CuttingPlaneDragger extends OrbitDragger {
|
|
34557
|
-
constructor(viewer) {
|
|
34432
|
+
constructor(viewer, normal) {
|
|
34558
34433
|
super(viewer);
|
|
34559
|
-
this.helpers = [];
|
|
34560
|
-
this.activeHelper = null;
|
|
34561
34434
|
this.transformChange = () => {
|
|
34562
|
-
|
|
34563
|
-
|
|
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);
|
|
34435
|
+
this.plane.normal.copy(new Vector3(0, 0, -1)).applyQuaternion(this.planeCenter.quaternion);
|
|
34436
|
+
this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
|
|
34567
34437
|
this.viewer.update();
|
|
34568
|
-
this.changed = true;
|
|
34569
34438
|
};
|
|
34570
34439
|
this.translateDrag = (event) => {
|
|
34571
34440
|
this.orbit.enabled = !event.value;
|
|
@@ -34576,83 +34445,45 @@ void main() {
|
|
|
34576
34445
|
this.translate.enabled = !event.value;
|
|
34577
34446
|
};
|
|
34578
34447
|
this.updatePlaneSize = () => {
|
|
34579
|
-
|
|
34580
|
-
this.helpers.forEach((planeHelper) => (planeHelper.size = extentsSize));
|
|
34448
|
+
this.planeHelper.size = this.viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34581
34449
|
this.viewer.update();
|
|
34582
34450
|
};
|
|
34583
34451
|
this.updateTransformCamera = () => {
|
|
34584
34452
|
this.translate.camera = this.viewer.camera;
|
|
34585
34453
|
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
34454
|
};
|
|
34597
34455
|
this.onKeyDown = (event) => {
|
|
34598
34456
|
if (event.key === "Shift")
|
|
34599
34457
|
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
34458
|
};
|
|
34605
34459
|
this.onKeyUp = (event) => {
|
|
34606
34460
|
if (event.key === "Shift")
|
|
34607
34461
|
this.rotate.setRotationSnap(null);
|
|
34608
34462
|
};
|
|
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));
|
|
34628
|
-
};
|
|
34629
34463
|
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();
|
|
34638
34464
|
event.stopPropagation();
|
|
34465
|
+
this.planeCenter.rotateOnAxis(new Vector3(0, 1, 0), Math.PI);
|
|
34466
|
+
this.transformChange();
|
|
34639
34467
|
};
|
|
34468
|
+
const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34469
|
+
const extentsCenter = viewer.extents.getCenter(new Vector3());
|
|
34470
|
+
const constant = -extentsCenter.dot(normal);
|
|
34471
|
+
this.plane = new Plane(normal, constant);
|
|
34640
34472
|
if (!viewer.renderer.clippingPlanes)
|
|
34641
34473
|
viewer.renderer.clippingPlanes = [];
|
|
34642
|
-
|
|
34643
|
-
this.
|
|
34644
|
-
|
|
34645
|
-
this.
|
|
34646
|
-
this.
|
|
34647
|
-
this.
|
|
34648
|
-
this.
|
|
34649
|
-
this.quaternion0 = new Quaternion();
|
|
34474
|
+
viewer.renderer.clippingPlanes.push(this.plane);
|
|
34475
|
+
this.planeCenter = new Object3D();
|
|
34476
|
+
this.planeCenter.position.copy(extentsCenter);
|
|
34477
|
+
this.planeCenter.quaternion.setFromUnitVectors(new Vector3(0, 0, -1), normal);
|
|
34478
|
+
this.viewer.helpers.add(this.planeCenter);
|
|
34479
|
+
this.planeHelper = new PlaneHelper2(extentsSize);
|
|
34480
|
+
this.planeCenter.add(this.planeHelper);
|
|
34650
34481
|
this.translate = new TransformControls(viewer.camera, viewer.canvas);
|
|
34651
|
-
this.translate.setMode("translate");
|
|
34652
34482
|
this.translate.setSpace("local");
|
|
34653
34483
|
this.translate.showX = false;
|
|
34654
34484
|
this.translate.showY = false;
|
|
34655
34485
|
this.translate.showZ = true;
|
|
34486
|
+
this.translate.attach(this.planeCenter);
|
|
34656
34487
|
this.translate.addEventListener("change", this.transformChange);
|
|
34657
34488
|
this.translate.addEventListener("dragging-changed", this.translateDrag);
|
|
34658
34489
|
this.viewer.helpers.add(this.translate.getHelper());
|
|
@@ -34662,18 +34493,14 @@ void main() {
|
|
|
34662
34493
|
this.rotate.showX = true;
|
|
34663
34494
|
this.rotate.showY = true;
|
|
34664
34495
|
this.rotate.showZ = false;
|
|
34496
|
+
this.rotate.attach(this.planeCenter);
|
|
34665
34497
|
this.rotate.addEventListener("change", this.transformChange);
|
|
34666
34498
|
this.rotate.addEventListener("dragging-changed", this.rotateDrag);
|
|
34667
34499
|
this.viewer.helpers.add(this.rotate.getHelper());
|
|
34668
|
-
this.setActiveHelper(this.helpers[this.helpers.length - 1]);
|
|
34669
34500
|
this.viewer.addEventListener("explode", this.updatePlaneSize);
|
|
34670
34501
|
this.viewer.addEventListener("show", this.updatePlaneSize);
|
|
34671
34502
|
this.viewer.addEventListener("showall", this.updatePlaneSize);
|
|
34672
34503
|
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);
|
|
34677
34504
|
this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
|
|
34678
34505
|
window.addEventListener("keydown", this.onKeyDown);
|
|
34679
34506
|
window.addEventListener("keyup", this.onKeyUp);
|
|
@@ -34684,10 +34511,6 @@ void main() {
|
|
|
34684
34511
|
this.viewer.removeEventListener("show", this.updatePlaneSize);
|
|
34685
34512
|
this.viewer.removeEventListener("showall", this.updatePlaneSize);
|
|
34686
34513
|
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);
|
|
34691
34514
|
this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
|
|
34692
34515
|
window.removeEventListener("keydown", this.onKeyDown);
|
|
34693
34516
|
window.removeEventListener("keyup", this.onKeyUp);
|
|
@@ -34701,108 +34524,28 @@ void main() {
|
|
|
34701
34524
|
this.rotate.getHelper().removeFromParent();
|
|
34702
34525
|
this.rotate.detach();
|
|
34703
34526
|
this.rotate.dispose();
|
|
34704
|
-
this.
|
|
34705
|
-
|
|
34706
|
-
|
|
34707
|
-
});
|
|
34708
|
-
this.helpers = [];
|
|
34709
|
-
this.activeHelper = null;
|
|
34527
|
+
this.planeHelper.removeFromParent();
|
|
34528
|
+
this.planeHelper.dispose();
|
|
34529
|
+
this.planeCenter.removeFromParent();
|
|
34710
34530
|
super.dispose();
|
|
34711
34531
|
}
|
|
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
|
-
}
|
|
34786
34532
|
}
|
|
34787
34533
|
|
|
34788
34534
|
class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
|
|
34789
34535
|
constructor(viewer) {
|
|
34790
|
-
super(viewer);
|
|
34791
|
-
this.addPlaneX();
|
|
34536
|
+
super(viewer, new Vector3(-1, 0, 0));
|
|
34792
34537
|
}
|
|
34793
34538
|
}
|
|
34794
34539
|
|
|
34795
34540
|
class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
|
|
34796
34541
|
constructor(viewer) {
|
|
34797
|
-
super(viewer);
|
|
34798
|
-
this.addPlaneY();
|
|
34542
|
+
super(viewer, new Vector3(0, -1, 0));
|
|
34799
34543
|
}
|
|
34800
34544
|
}
|
|
34801
34545
|
|
|
34802
34546
|
class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
|
|
34803
34547
|
constructor(viewer) {
|
|
34804
|
-
super(viewer);
|
|
34805
|
-
this.addPlaneZ();
|
|
34548
|
+
super(viewer, new Vector3(0, 0, -1));
|
|
34806
34549
|
}
|
|
34807
34550
|
}
|
|
34808
34551
|
|
|
@@ -34879,6 +34622,120 @@ void main() {
|
|
|
34879
34622
|
}
|
|
34880
34623
|
}
|
|
34881
34624
|
|
|
34625
|
+
const DESKTOP_SNAP_DISTANCE = 10;
|
|
34626
|
+
const MOBILE_SNAP_DISTANCE = 50;
|
|
34627
|
+
const _vertex = new Vector3();
|
|
34628
|
+
const _start$1 = new Vector3();
|
|
34629
|
+
const _end$1 = new Vector3();
|
|
34630
|
+
const _line = new Line3();
|
|
34631
|
+
const _center = new Vector3();
|
|
34632
|
+
const _projection = new Vector3();
|
|
34633
|
+
class Snapper {
|
|
34634
|
+
constructor(camera, renderer, canvas) {
|
|
34635
|
+
this.camera = camera;
|
|
34636
|
+
this.renderer = renderer;
|
|
34637
|
+
this.canvas = canvas;
|
|
34638
|
+
this.threshold = 0.0001;
|
|
34639
|
+
this.raycaster = new Raycaster();
|
|
34640
|
+
this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
|
|
34641
|
+
this.edgesCache = new WeakMap();
|
|
34642
|
+
}
|
|
34643
|
+
isMobile() {
|
|
34644
|
+
if (typeof navigator === "undefined")
|
|
34645
|
+
return false;
|
|
34646
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
|
|
34647
|
+
}
|
|
34648
|
+
getMousePosition(event, target) {
|
|
34649
|
+
return target.set(event.clientX, event.clientY);
|
|
34650
|
+
}
|
|
34651
|
+
getPointerIntersects(mouse, objects) {
|
|
34652
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
34653
|
+
const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
|
|
34654
|
+
const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
|
|
34655
|
+
const coords = new Vector2(x, y);
|
|
34656
|
+
this.raycaster.setFromCamera(coords, this.camera);
|
|
34657
|
+
this.raycaster.params = {
|
|
34658
|
+
Mesh: {},
|
|
34659
|
+
Line: { threshold: this.threshold },
|
|
34660
|
+
Line2: { threshold: this.threshold },
|
|
34661
|
+
LOD: {},
|
|
34662
|
+
Points: { threshold: this.threshold },
|
|
34663
|
+
Sprite: {},
|
|
34664
|
+
};
|
|
34665
|
+
let intersects = this.raycaster.intersectObjects(objects, false);
|
|
34666
|
+
(this.renderer.clippingPlanes || []).forEach((plane) => {
|
|
34667
|
+
intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
|
|
34668
|
+
});
|
|
34669
|
+
return intersects;
|
|
34670
|
+
}
|
|
34671
|
+
getDetectRadius(point) {
|
|
34672
|
+
const camera = this.camera;
|
|
34673
|
+
if (camera.isOrthographicCamera) {
|
|
34674
|
+
const fieldHeight = (camera.top - camera.bottom) / camera.zoom;
|
|
34675
|
+
const canvasHeight = this.canvas.height;
|
|
34676
|
+
const worldUnitsPerPixel = fieldHeight / canvasHeight;
|
|
34677
|
+
return this.detectRadiusInPixels * worldUnitsPerPixel;
|
|
34678
|
+
}
|
|
34679
|
+
if (camera.isPerspectiveCamera) {
|
|
34680
|
+
const distance = camera.position.distanceTo(point);
|
|
34681
|
+
const fieldHeight = 2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5)) * distance;
|
|
34682
|
+
const canvasHeight = this.canvas.height;
|
|
34683
|
+
const worldUnitsPerPixel = fieldHeight / canvasHeight;
|
|
34684
|
+
return this.detectRadiusInPixels * worldUnitsPerPixel;
|
|
34685
|
+
}
|
|
34686
|
+
return 0.1;
|
|
34687
|
+
}
|
|
34688
|
+
getSnapPoint(mouse, objects) {
|
|
34689
|
+
const intersections = this.getPointerIntersects(mouse, objects);
|
|
34690
|
+
if (intersections.length === 0)
|
|
34691
|
+
return undefined;
|
|
34692
|
+
const object = intersections[0].object;
|
|
34693
|
+
const intersectionPoint = intersections[0].point;
|
|
34694
|
+
const localPoint = object.worldToLocal(intersectionPoint.clone());
|
|
34695
|
+
let snapPoint;
|
|
34696
|
+
let snapDistance = this.getDetectRadius(intersectionPoint);
|
|
34697
|
+
const geometry = object.geometry;
|
|
34698
|
+
const positions = geometry.attributes.position.array;
|
|
34699
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
34700
|
+
_vertex.set(positions[i], positions[i + 1], positions[i + 2]);
|
|
34701
|
+
const distance = _vertex.distanceTo(localPoint);
|
|
34702
|
+
if (distance < snapDistance) {
|
|
34703
|
+
snapDistance = distance;
|
|
34704
|
+
snapPoint = _vertex.clone();
|
|
34705
|
+
}
|
|
34706
|
+
}
|
|
34707
|
+
if (snapPoint)
|
|
34708
|
+
return object.localToWorld(snapPoint);
|
|
34709
|
+
let edges = this.edgesCache.get(geometry);
|
|
34710
|
+
if (!edges) {
|
|
34711
|
+
edges = new EdgesGeometry(geometry);
|
|
34712
|
+
this.edgesCache.set(geometry, edges);
|
|
34713
|
+
}
|
|
34714
|
+
const edgePositions = edges.attributes.position.array;
|
|
34715
|
+
for (let i = 0; i < edgePositions.length; i += 6) {
|
|
34716
|
+
_start$1.set(edgePositions[i], edgePositions[i + 1], edgePositions[i + 2]);
|
|
34717
|
+
_end$1.set(edgePositions[i + 3], edgePositions[i + 4], edgePositions[i + 5]);
|
|
34718
|
+
_line.set(_start$1, _end$1);
|
|
34719
|
+
_line.getCenter(_center);
|
|
34720
|
+
const centerDistance = _center.distanceTo(localPoint);
|
|
34721
|
+
if (centerDistance < snapDistance) {
|
|
34722
|
+
snapDistance = centerDistance;
|
|
34723
|
+
snapPoint = _center.clone();
|
|
34724
|
+
continue;
|
|
34725
|
+
}
|
|
34726
|
+
_line.closestPointToPoint(localPoint, true, _projection);
|
|
34727
|
+
const lineDistance = _projection.distanceTo(localPoint);
|
|
34728
|
+
if (lineDistance < snapDistance) {
|
|
34729
|
+
snapDistance = lineDistance;
|
|
34730
|
+
snapPoint = _projection.clone();
|
|
34731
|
+
}
|
|
34732
|
+
}
|
|
34733
|
+
if (snapPoint)
|
|
34734
|
+
return object.localToWorld(snapPoint);
|
|
34735
|
+
return intersectionPoint.clone();
|
|
34736
|
+
}
|
|
34737
|
+
}
|
|
34738
|
+
|
|
34882
34739
|
const _downPoint = new Vector2();
|
|
34883
34740
|
class MeasureLineDragger extends OrbitDragger {
|
|
34884
34741
|
constructor(viewer) {
|
|
@@ -35290,12 +35147,6 @@ void main() {
|
|
|
35290
35147
|
this.movementSpeed = 0.1;
|
|
35291
35148
|
this.multiplier = 3;
|
|
35292
35149
|
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();
|
|
35299
35150
|
this.moveWheel = 0;
|
|
35300
35151
|
this.mouseDragOn = false;
|
|
35301
35152
|
this._up = new Vector3();
|
|
@@ -35362,20 +35213,11 @@ void main() {
|
|
|
35362
35213
|
}
|
|
35363
35214
|
};
|
|
35364
35215
|
this.onKeyUp = (event) => {
|
|
35365
|
-
if (this.moveKeys.delete(event.code))
|
|
35366
|
-
if (this.moveKeys.size === 0) {
|
|
35367
|
-
this._rebuildGroundBox(this.object.position);
|
|
35368
|
-
}
|
|
35216
|
+
if (this.moveKeys.delete(event.code))
|
|
35369
35217
|
this.update();
|
|
35370
|
-
}
|
|
35371
35218
|
};
|
|
35372
35219
|
this.camera = camera;
|
|
35373
35220
|
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);
|
|
35379
35221
|
this.raycaster = new Raycaster();
|
|
35380
35222
|
this.raycaster.near = 0;
|
|
35381
35223
|
this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
|
|
@@ -35410,29 +35252,10 @@ void main() {
|
|
|
35410
35252
|
window.removeEventListener("keyup", this.onKeyUp);
|
|
35411
35253
|
super.dispose();
|
|
35412
35254
|
}
|
|
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
|
-
}
|
|
35428
35255
|
updateGroundFollowing() {
|
|
35429
|
-
const pos = this.object.position;
|
|
35430
|
-
if (this._needsGroundBoxRebuild(pos)) {
|
|
35431
|
-
this._rebuildGroundBox(pos);
|
|
35432
|
-
}
|
|
35433
35256
|
this._up.copy(this.camera.up).negate();
|
|
35434
|
-
this.raycaster.set(
|
|
35435
|
-
const intersects = this.raycaster.intersectObjects(this.
|
|
35257
|
+
this.raycaster.set(this.object.position, this._up);
|
|
35258
|
+
const intersects = this.raycaster.intersectObjects(this.groundObjects, false);
|
|
35436
35259
|
if (intersects.length > 0) {
|
|
35437
35260
|
const groundY = intersects[0].point.y;
|
|
35438
35261
|
const targetY = groundY + this.EYE_HEIGHT;
|
|
@@ -35984,7 +35807,6 @@ void main() {
|
|
|
35984
35807
|
draggers.registerDragger("Orbit", (viewer) => new OrbitDragger(viewer));
|
|
35985
35808
|
draggers.registerDragger("Zoom", (viewer) => new ZoomDragger(viewer));
|
|
35986
35809
|
draggers.registerDragger("MeasureLine", (viewer) => new MeasureLineDragger(viewer));
|
|
35987
|
-
draggers.registerDragger("CuttingPlane", (viewer) => new CuttingPlaneDragger(viewer));
|
|
35988
35810
|
draggers.registerDragger("CuttingPlaneXAxis", (viewer) => new CuttingPlaneXAxisDragger(viewer));
|
|
35989
35811
|
draggers.registerDragger("CuttingPlaneYAxis", (viewer) => new CuttingPlaneYAxisDragger(viewer));
|
|
35990
35812
|
draggers.registerDragger("CuttingPlaneZAxis", (viewer) => new CuttingPlaneZAxisDragger(viewer));
|
|
@@ -37519,7 +37341,7 @@ void main() {
|
|
|
37519
37341
|
this.getMousePosition(event, this.downPosition);
|
|
37520
37342
|
};
|
|
37521
37343
|
this.onPointerUp = (event) => {
|
|
37522
|
-
if (!event.isPrimary
|
|
37344
|
+
if (!event.isPrimary)
|
|
37523
37345
|
return;
|
|
37524
37346
|
const upPosition = this.getMousePosition(event, new Vector2());
|
|
37525
37347
|
if (upPosition.distanceTo(this.downPosition) !== 0)
|
|
@@ -38982,81 +38804,6 @@ void main() {
|
|
|
38982
38804
|
this.mergedObjectMap = new Map();
|
|
38983
38805
|
this.mergedGeometryVisibility = new Map();
|
|
38984
38806
|
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;
|
|
39060
38807
|
}
|
|
39061
38808
|
setVisibleEdges(visible) {
|
|
39062
38809
|
this.visibleEdges = visible;
|
|
@@ -39946,82 +39693,36 @@ void main() {
|
|
|
39946
39693
|
}
|
|
39947
39694
|
}
|
|
39948
39695
|
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;
|
|
39955
39696
|
material.onBeforeCompile = (shader) => {
|
|
39956
|
-
shader.uniforms.transformTexture = uniforms.transformTexture;
|
|
39957
|
-
shader.uniforms.transformTextureSize = uniforms.transformTextureSize;
|
|
39958
39697
|
shader.vertexShader = shader.vertexShader.replace(
|
|
39959
39698
|
"#include <common>",
|
|
39960
39699
|
`
|
|
39961
39700
|
#include <common>
|
|
39962
|
-
|
|
39963
39701
|
attribute float visibility;
|
|
39964
|
-
attribute float objectId;
|
|
39965
39702
|
varying float vVisibility;
|
|
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
|
-
}
|
|
39983
39703
|
`
|
|
39984
39704
|
);
|
|
39985
|
-
shader.
|
|
39986
|
-
"
|
|
39705
|
+
shader.fragmentShader = shader.fragmentShader.replace(
|
|
39706
|
+
"#include <common>",
|
|
39987
39707
|
`
|
|
39988
|
-
|
|
39989
|
-
|
|
39990
|
-
vVisibility = visibility;
|
|
39708
|
+
#include <common>
|
|
39709
|
+
varying float vVisibility;
|
|
39991
39710
|
`
|
|
39992
39711
|
);
|
|
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;
|
|
40000
|
-
`
|
|
40001
|
-
);
|
|
40002
|
-
}
|
|
40003
39712
|
shader.vertexShader = shader.vertexShader.replace(
|
|
40004
|
-
"
|
|
39713
|
+
"void main() {",
|
|
40005
39714
|
`
|
|
40006
|
-
|
|
40007
|
-
|
|
39715
|
+
void main() {
|
|
39716
|
+
vVisibility = visibility;
|
|
40008
39717
|
`
|
|
40009
39718
|
);
|
|
40010
|
-
shader.fragmentShader = shader.fragmentShader
|
|
40011
|
-
|
|
40012
|
-
|
|
40013
|
-
`
|
|
40014
|
-
#include <common>
|
|
40015
|
-
varying float vVisibility;
|
|
40016
|
-
`
|
|
40017
|
-
)
|
|
40018
|
-
.replace(
|
|
40019
|
-
"void main() {",
|
|
40020
|
-
`
|
|
39719
|
+
shader.fragmentShader = shader.fragmentShader.replace(
|
|
39720
|
+
"void main() {",
|
|
39721
|
+
`
|
|
40021
39722
|
void main() {
|
|
40022
39723
|
if (vVisibility < 0.5) discard;
|
|
40023
39724
|
`
|
|
40024
|
-
|
|
39725
|
+
);
|
|
40025
39726
|
};
|
|
40026
39727
|
material.needsUpdate = true;
|
|
40027
39728
|
return material;
|
|
@@ -40136,8 +39837,6 @@ void main() {
|
|
|
40136
39837
|
this.objectIdToIndex.clear();
|
|
40137
39838
|
this.maxObjectId = 0;
|
|
40138
39839
|
this.objectVisibility = new Float32Array();
|
|
40139
|
-
this.meshToNodeMap = null;
|
|
40140
|
-
this.visibilityMaterials.clear();
|
|
40141
39840
|
}
|
|
40142
39841
|
setStructureTransform(structureId, matrix) {
|
|
40143
39842
|
const rootGroup = this.structureRoots.get(structureId);
|
|
@@ -40253,15 +39952,12 @@ void main() {
|
|
|
40253
39952
|
});
|
|
40254
39953
|
this.originalObjects.clear();
|
|
40255
39954
|
this.originalObjectsToSelection.clear();
|
|
40256
|
-
this.objectIdToIndex.clear();
|
|
40257
|
-
this.maxObjectId = 0;
|
|
40258
39955
|
const structureGroups = new Map();
|
|
40259
39956
|
this.dispatchEvent("optimizationprogress", {
|
|
40260
39957
|
phase: "collecting",
|
|
40261
39958
|
progress: 5,
|
|
40262
39959
|
message: "Collecting scene objects...",
|
|
40263
39960
|
});
|
|
40264
|
-
let totalObjectsToMerge = 0;
|
|
40265
39961
|
this.scene.traverse((object) => {
|
|
40266
39962
|
if (object.userData.structureId) {
|
|
40267
39963
|
const structureId = object.userData.structureId;
|
|
@@ -40279,32 +39975,17 @@ void main() {
|
|
|
40279
39975
|
});
|
|
40280
39976
|
}
|
|
40281
39977
|
const group = structureGroups.get(structureId);
|
|
40282
|
-
let added = false;
|
|
40283
39978
|
if (object instanceof Mesh) {
|
|
40284
39979
|
this.addToMaterialGroup(object, group.mapMeshes, group.meshes);
|
|
40285
|
-
added = true;
|
|
40286
39980
|
} else if (object instanceof LineSegments) {
|
|
40287
39981
|
this.addToMaterialGroup(object, group.mapLineSegments, group.lineSegments);
|
|
40288
|
-
added = true;
|
|
40289
39982
|
} else if (object instanceof Line$1) {
|
|
40290
39983
|
this.addToMaterialGroup(object, group.mapLines, group.lines);
|
|
40291
|
-
added = true;
|
|
40292
39984
|
} else if (object instanceof Points) {
|
|
40293
39985
|
this.addToMaterialGroup(object, group.mapPoints, group.points);
|
|
40294
|
-
added = true;
|
|
40295
|
-
}
|
|
40296
|
-
if (added) {
|
|
40297
|
-
totalObjectsToMerge++;
|
|
40298
39986
|
}
|
|
40299
39987
|
}
|
|
40300
39988
|
});
|
|
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
|
-
}
|
|
40308
39989
|
let processedGroups = 0;
|
|
40309
39990
|
const totalGroups = structureGroups.size;
|
|
40310
39991
|
this.dispatchEvent("optimizationprogress", {
|
|
@@ -40349,6 +40030,7 @@ void main() {
|
|
|
40349
40030
|
this.originalObjectsToSelection.add(obj);
|
|
40350
40031
|
}
|
|
40351
40032
|
});
|
|
40033
|
+
this.initializeObjectVisibility();
|
|
40352
40034
|
console.log(`Optimization complete. Total objects: ${this.maxObjectId}`);
|
|
40353
40035
|
this.dispatchEvent("optimizationprogress", {
|
|
40354
40036
|
phase: "complete",
|
|
@@ -40417,7 +40099,6 @@ void main() {
|
|
|
40417
40099
|
}
|
|
40418
40100
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40419
40101
|
const mergedMesh = new Mesh(mergedGeometry, visibilityMaterial);
|
|
40420
|
-
mergedMesh.frustumCulled = false;
|
|
40421
40102
|
mergedMesh.userData.isOptimized = true;
|
|
40422
40103
|
rootGroup.add(mergedMesh);
|
|
40423
40104
|
this.mergedMesh.add(mergedMesh);
|
|
@@ -40534,7 +40215,6 @@ void main() {
|
|
|
40534
40215
|
geometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40535
40216
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40536
40217
|
const mergedLine = new LineSegments(geometry, visibilityMaterial);
|
|
40537
|
-
mergedLine.frustumCulled = false;
|
|
40538
40218
|
mergedLine.userData.isEdge = isEdge;
|
|
40539
40219
|
mergedLine.userData.isOptimized = true;
|
|
40540
40220
|
const mergedObjects = [mergedLine];
|
|
@@ -40623,7 +40303,6 @@ void main() {
|
|
|
40623
40303
|
mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40624
40304
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40625
40305
|
const mergedLine = new LineSegments(mergedGeometry, visibilityMaterial);
|
|
40626
|
-
mergedLine.frustumCulled = false;
|
|
40627
40306
|
mergedLine.userData.isEdge = isEdge;
|
|
40628
40307
|
mergedLine.userData.isOptimized = true;
|
|
40629
40308
|
if (this.useVAO) {
|
|
@@ -40693,27 +40372,7 @@ void main() {
|
|
|
40693
40372
|
const mergedObjects = [];
|
|
40694
40373
|
if (geometries.length > 0) {
|
|
40695
40374
|
const mergedGeometry = mergeGeometries(geometries, false);
|
|
40696
|
-
const
|
|
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;
|
|
40375
|
+
const mergedPoints = new Points(mergedGeometry, group.material);
|
|
40717
40376
|
mergedPoints.userData.isOptimized = true;
|
|
40718
40377
|
if (this.useVAO) {
|
|
40719
40378
|
this.createVAO(mergedPoints);
|
|
@@ -40782,33 +40441,13 @@ void main() {
|
|
|
40782
40441
|
geometriesWithIndex.push(clonedGeometry);
|
|
40783
40442
|
});
|
|
40784
40443
|
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));
|
|
40803
40444
|
const material = new LineBasicMaterial({
|
|
40804
40445
|
vertexColors: true,
|
|
40805
40446
|
});
|
|
40806
|
-
const visibilityMaterial = this.createVisibilityMaterial(material);
|
|
40807
40447
|
if (this.useVAO) {
|
|
40808
40448
|
this.createVAO(finalGeometry);
|
|
40809
40449
|
}
|
|
40810
|
-
const mergedLine = new LineSegments(finalGeometry,
|
|
40811
|
-
mergedLine.frustumCulled = false;
|
|
40450
|
+
const mergedLine = new LineSegments(finalGeometry, material);
|
|
40812
40451
|
mergedLine.userData.structureId = structureId;
|
|
40813
40452
|
mergedLine.userData.isOptimized = true;
|
|
40814
40453
|
rootGroup.add(mergedLine);
|
|
@@ -40927,50 +40566,18 @@ void main() {
|
|
|
40927
40566
|
console.warn("No merged objects to transform");
|
|
40928
40567
|
return;
|
|
40929
40568
|
}
|
|
40930
|
-
|
|
40931
|
-
|
|
40932
|
-
|
|
40569
|
+
this.objectTransforms = new Map(objectTransformMap);
|
|
40570
|
+
for (const mesh of this.mergedMesh) {
|
|
40571
|
+
this._applyTransformToMergedObject(mesh);
|
|
40933
40572
|
}
|
|
40934
|
-
this.
|
|
40935
|
-
|
|
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
|
-
}
|
|
40573
|
+
for (const line of this.mergedLines) {
|
|
40574
|
+
this._applyTransformToMergedObject(line);
|
|
40965
40575
|
}
|
|
40966
|
-
|
|
40967
|
-
this.
|
|
40968
|
-
|
|
40969
|
-
|
|
40970
|
-
|
|
40971
|
-
) {
|
|
40972
|
-
this.updateMaterialUniforms();
|
|
40973
|
-
}
|
|
40576
|
+
for (const lineSegment of this.mergedLineSegments) {
|
|
40577
|
+
this._applyTransformToMergedObject(lineSegment);
|
|
40578
|
+
}
|
|
40579
|
+
for (const point of this.mergedPoints) {
|
|
40580
|
+
this._applyTransformToMergedObject(point);
|
|
40974
40581
|
}
|
|
40975
40582
|
}
|
|
40976
40583
|
createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
|
|
@@ -40987,66 +40594,21 @@ void main() {
|
|
|
40987
40594
|
? objects
|
|
40988
40595
|
: Array.from(objects)
|
|
40989
40596
|
: 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
|
-
}
|
|
40999
40597
|
for (const obj of objectsArray) {
|
|
41000
40598
|
if (!obj.geometry || !obj.geometry.attributes.position) continue;
|
|
41001
|
-
|
|
41002
|
-
|
|
41003
|
-
|
|
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;
|
|
40599
|
+
const boundingBox = new Box3().setFromBufferAttribute(obj.geometry.attributes.position);
|
|
40600
|
+
if (obj.matrixWorld) {
|
|
40601
|
+
boundingBox.applyMatrix4(obj.matrixWorld);
|
|
41019
40602
|
}
|
|
41020
|
-
|
|
41021
|
-
const
|
|
40603
|
+
if (boundingBox.isEmpty()) continue;
|
|
40604
|
+
const objectCenter = new Vector3();
|
|
40605
|
+
boundingBox.getCenter(objectCenter);
|
|
40606
|
+
const direction = objectCenter.clone().sub(explodeCenter);
|
|
40607
|
+
const distance = direction.length();
|
|
41022
40608
|
if (distance > 0) {
|
|
41023
|
-
|
|
41024
|
-
const
|
|
41025
|
-
|
|
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);
|
|
40609
|
+
direction.normalize();
|
|
40610
|
+
const offset = direction.multiplyScalar(distance * (explodeFactor - 1.0));
|
|
40611
|
+
const matrix = new Matrix4().makeTranslation(offset.x, offset.y, offset.z);
|
|
41050
40612
|
transformMap.set(obj, matrix);
|
|
41051
40613
|
}
|
|
41052
40614
|
}
|
|
@@ -41054,11 +40616,116 @@ void main() {
|
|
|
41054
40616
|
}
|
|
41055
40617
|
clearTransforms() {
|
|
41056
40618
|
this.objectTransforms.clear();
|
|
41057
|
-
this.
|
|
40619
|
+
for (const mesh of this.mergedMesh) {
|
|
40620
|
+
this._restoreOriginalGeometry(mesh);
|
|
40621
|
+
}
|
|
40622
|
+
for (const line of this.mergedLines) {
|
|
40623
|
+
this._restoreOriginalGeometry(line);
|
|
40624
|
+
}
|
|
40625
|
+
for (const lineSegment of this.mergedLineSegments) {
|
|
40626
|
+
this._restoreOriginalGeometry(lineSegment);
|
|
40627
|
+
}
|
|
40628
|
+
for (const point of this.mergedPoints) {
|
|
40629
|
+
this._restoreOriginalGeometry(point);
|
|
40630
|
+
}
|
|
41058
40631
|
}
|
|
41059
40632
|
clearHandleTransforms() {
|
|
41060
40633
|
this.clearTransforms();
|
|
41061
40634
|
}
|
|
40635
|
+
_applyTransformToMergedObject(mergedObject) {
|
|
40636
|
+
const objectData = this.mergedObjectMap.get(mergedObject.uuid);
|
|
40637
|
+
if (!objectData || !objectData.objectMapping) return;
|
|
40638
|
+
const geometry = mergedObject.geometry;
|
|
40639
|
+
if (!geometry || !geometry.attributes.position) return;
|
|
40640
|
+
const positionAttr = geometry.attributes.position;
|
|
40641
|
+
const positions = positionAttr.array;
|
|
40642
|
+
if (!this.transformedGeometries.has(mergedObject.uuid)) {
|
|
40643
|
+
this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
|
|
40644
|
+
}
|
|
40645
|
+
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
40646
|
+
const tempVector = new Vector3();
|
|
40647
|
+
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
40648
|
+
const transform = this.objectTransforms.get(originalMesh);
|
|
40649
|
+
if (!transform) {
|
|
40650
|
+
const startIdx = mappingData.startVertexIndex * 3;
|
|
40651
|
+
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
40652
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
40653
|
+
positions[i] = originalPositions[i];
|
|
40654
|
+
}
|
|
40655
|
+
continue;
|
|
40656
|
+
}
|
|
40657
|
+
const startVertex = mappingData.startVertexIndex;
|
|
40658
|
+
const vertexCount = mappingData.vertexCount;
|
|
40659
|
+
for (let i = 0; i < vertexCount; i++) {
|
|
40660
|
+
const idx = (startVertex + i) * 3;
|
|
40661
|
+
tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
|
|
40662
|
+
tempVector.applyMatrix4(transform);
|
|
40663
|
+
positions[idx] = tempVector.x;
|
|
40664
|
+
positions[idx + 1] = tempVector.y;
|
|
40665
|
+
positions[idx + 2] = tempVector.z;
|
|
40666
|
+
}
|
|
40667
|
+
}
|
|
40668
|
+
if (geometry.attributes.normal) {
|
|
40669
|
+
this._updateNormalsForTransform(geometry, objectData, originalPositions);
|
|
40670
|
+
}
|
|
40671
|
+
positionAttr.needsUpdate = true;
|
|
40672
|
+
geometry.computeBoundingSphere();
|
|
40673
|
+
geometry.computeBoundingBox();
|
|
40674
|
+
}
|
|
40675
|
+
_updateNormalsForTransform(geometry, objectData, originalPositions) {
|
|
40676
|
+
const normalAttr = geometry.attributes.normal;
|
|
40677
|
+
if (!normalAttr) return;
|
|
40678
|
+
const normals = normalAttr.array;
|
|
40679
|
+
const tempVector = new Vector3();
|
|
40680
|
+
const normalMatrix = new Matrix4();
|
|
40681
|
+
const normalsKey = `${geometry.uuid}_normals`;
|
|
40682
|
+
if (!this.transformedGeometries.has(normalsKey)) {
|
|
40683
|
+
this.transformedGeometries.set(normalsKey, new Float32Array(normals));
|
|
40684
|
+
}
|
|
40685
|
+
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
40686
|
+
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
40687
|
+
const transform = this.objectTransforms.get(originalMesh);
|
|
40688
|
+
if (!transform) {
|
|
40689
|
+
const startIdx = mappingData.startVertexIndex * 3;
|
|
40690
|
+
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
40691
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
40692
|
+
normals[i] = originalNormals[i];
|
|
40693
|
+
}
|
|
40694
|
+
continue;
|
|
40695
|
+
}
|
|
40696
|
+
normalMatrix.copy(transform).invert().transpose();
|
|
40697
|
+
const startVertex = mappingData.startVertexIndex;
|
|
40698
|
+
const vertexCount = mappingData.vertexCount;
|
|
40699
|
+
for (let i = 0; i < vertexCount; i++) {
|
|
40700
|
+
const idx = (startVertex + i) * 3;
|
|
40701
|
+
tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
|
|
40702
|
+
tempVector.applyMatrix4(normalMatrix).normalize();
|
|
40703
|
+
normals[idx] = tempVector.x;
|
|
40704
|
+
normals[idx + 1] = tempVector.y;
|
|
40705
|
+
normals[idx + 2] = tempVector.z;
|
|
40706
|
+
}
|
|
40707
|
+
}
|
|
40708
|
+
normalAttr.needsUpdate = true;
|
|
40709
|
+
}
|
|
40710
|
+
_restoreOriginalGeometry(mergedObject) {
|
|
40711
|
+
const geometry = mergedObject.geometry;
|
|
40712
|
+
if (!geometry || !geometry.attributes.position) return;
|
|
40713
|
+
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
40714
|
+
if (originalPositions) {
|
|
40715
|
+
const positions = geometry.attributes.position.array;
|
|
40716
|
+
positions.set(originalPositions);
|
|
40717
|
+
geometry.attributes.position.needsUpdate = true;
|
|
40718
|
+
}
|
|
40719
|
+
const normalsKey = `${geometry.uuid}_normals`;
|
|
40720
|
+
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
40721
|
+
if (originalNormals && geometry.attributes.normal) {
|
|
40722
|
+
const normals = geometry.attributes.normal.array;
|
|
40723
|
+
normals.set(originalNormals);
|
|
40724
|
+
geometry.attributes.normal.needsUpdate = true;
|
|
40725
|
+
}
|
|
40726
|
+
geometry.computeBoundingSphere();
|
|
40727
|
+
geometry.computeBoundingBox();
|
|
40728
|
+
}
|
|
41062
40729
|
syncHiddenObjects() {
|
|
41063
40730
|
if (this.mergedObjectMap.size === 0) {
|
|
41064
40731
|
console.log("No merged objects to sync");
|