@inweb/viewer-three 27.2.2 → 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 +622 -317
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +624 -319
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/draggers/CuttingPlaneDragger.d.ts +23 -5
- package/lib/Viewer/helpers/PlaneHelper2.d.ts +8 -4
- 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 +10 -2
- package/src/Viewer/draggers/CuttingPlaneDragger.ts +191 -31
- 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/PlaneHelper2.ts +30 -17
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +413 -189
- package/src/Viewer/measurement/Snapper.ts +13 -5
package/dist/viewer-three.js
CHANGED
|
@@ -33644,41 +33644,6 @@ 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
|
-
|
|
33682
33647
|
const _changeEvent = { type: "change" };
|
|
33683
33648
|
const _startEvent = { type: "start" };
|
|
33684
33649
|
const _endEvent = { type: "end" };
|
|
@@ -34337,6 +34302,166 @@ void main() {
|
|
|
34337
34302
|
}
|
|
34338
34303
|
}
|
|
34339
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
|
+
|
|
34340
34465
|
class OrbitDragger {
|
|
34341
34466
|
constructor(viewer) {
|
|
34342
34467
|
this.updateControls = () => {
|
|
@@ -34429,12 +34554,18 @@ void main() {
|
|
|
34429
34554
|
}
|
|
34430
34555
|
|
|
34431
34556
|
class CuttingPlaneDragger extends OrbitDragger {
|
|
34432
|
-
constructor(viewer
|
|
34557
|
+
constructor(viewer) {
|
|
34433
34558
|
super(viewer);
|
|
34559
|
+
this.helpers = [];
|
|
34560
|
+
this.activeHelper = null;
|
|
34434
34561
|
this.transformChange = () => {
|
|
34435
|
-
|
|
34436
|
-
|
|
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);
|
|
34437
34567
|
this.viewer.update();
|
|
34568
|
+
this.changed = true;
|
|
34438
34569
|
};
|
|
34439
34570
|
this.translateDrag = (event) => {
|
|
34440
34571
|
this.orbit.enabled = !event.value;
|
|
@@ -34445,45 +34576,83 @@ void main() {
|
|
|
34445
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
34584
|
this.translate.camera = this.viewer.camera;
|
|
34453
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();
|
|
34454
34596
|
};
|
|
34455
34597
|
this.onKeyDown = (event) => {
|
|
34456
34598
|
if (event.key === "Shift")
|
|
34457
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();
|
|
34458
34604
|
};
|
|
34459
34605
|
this.onKeyUp = (event) => {
|
|
34460
34606
|
if (event.key === "Shift")
|
|
34461
34607
|
this.rotate.setRotationSnap(null);
|
|
34462
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));
|
|
34628
|
+
};
|
|
34463
34629
|
this.onDoubleClick = (event) => {
|
|
34464
|
-
|
|
34465
|
-
|
|
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);
|
|
34466
34637
|
this.transformChange();
|
|
34638
|
+
event.stopPropagation();
|
|
34467
34639
|
};
|
|
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);
|
|
34472
34640
|
if (!viewer.renderer.clippingPlanes)
|
|
34473
34641
|
viewer.renderer.clippingPlanes = [];
|
|
34474
|
-
viewer.renderer.clippingPlanes
|
|
34475
|
-
this.
|
|
34476
|
-
|
|
34477
|
-
this.
|
|
34478
|
-
this.
|
|
34479
|
-
this.
|
|
34480
|
-
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();
|
|
34481
34650
|
this.translate = new TransformControls(viewer.camera, viewer.canvas);
|
|
34651
|
+
this.translate.setMode("translate");
|
|
34482
34652
|
this.translate.setSpace("local");
|
|
34483
34653
|
this.translate.showX = false;
|
|
34484
34654
|
this.translate.showY = false;
|
|
34485
34655
|
this.translate.showZ = true;
|
|
34486
|
-
this.translate.attach(this.planeCenter);
|
|
34487
34656
|
this.translate.addEventListener("change", this.transformChange);
|
|
34488
34657
|
this.translate.addEventListener("dragging-changed", this.translateDrag);
|
|
34489
34658
|
this.viewer.helpers.add(this.translate.getHelper());
|
|
@@ -34493,14 +34662,18 @@ void main() {
|
|
|
34493
34662
|
this.rotate.showX = true;
|
|
34494
34663
|
this.rotate.showY = true;
|
|
34495
34664
|
this.rotate.showZ = false;
|
|
34496
|
-
this.rotate.attach(this.planeCenter);
|
|
34497
34665
|
this.rotate.addEventListener("change", this.transformChange);
|
|
34498
34666
|
this.rotate.addEventListener("dragging-changed", this.rotateDrag);
|
|
34499
34667
|
this.viewer.helpers.add(this.rotate.getHelper());
|
|
34668
|
+
this.setActiveHelper(this.helpers[this.helpers.length - 1]);
|
|
34500
34669
|
this.viewer.addEventListener("explode", this.updatePlaneSize);
|
|
34501
34670
|
this.viewer.addEventListener("show", this.updatePlaneSize);
|
|
34502
34671
|
this.viewer.addEventListener("showall", this.updatePlaneSize);
|
|
34503
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);
|
|
34504
34677
|
this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
|
|
34505
34678
|
window.addEventListener("keydown", this.onKeyDown);
|
|
34506
34679
|
window.addEventListener("keyup", this.onKeyUp);
|
|
@@ -34511,6 +34684,10 @@ void main() {
|
|
|
34511
34684
|
this.viewer.removeEventListener("show", this.updatePlaneSize);
|
|
34512
34685
|
this.viewer.removeEventListener("showall", this.updatePlaneSize);
|
|
34513
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);
|
|
34514
34691
|
this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
|
|
34515
34692
|
window.removeEventListener("keydown", this.onKeyDown);
|
|
34516
34693
|
window.removeEventListener("keyup", this.onKeyUp);
|
|
@@ -34524,28 +34701,108 @@ void main() {
|
|
|
34524
34701
|
this.rotate.getHelper().removeFromParent();
|
|
34525
34702
|
this.rotate.detach();
|
|
34526
34703
|
this.rotate.dispose();
|
|
34527
|
-
this.
|
|
34528
|
-
|
|
34529
|
-
|
|
34704
|
+
this.helpers.forEach((helper) => {
|
|
34705
|
+
helper.removeFromParent();
|
|
34706
|
+
helper.dispose();
|
|
34707
|
+
});
|
|
34708
|
+
this.helpers = [];
|
|
34709
|
+
this.activeHelper = null;
|
|
34530
34710
|
super.dispose();
|
|
34531
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
|
+
}
|
|
34532
34786
|
}
|
|
34533
34787
|
|
|
34534
34788
|
class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
|
|
34535
34789
|
constructor(viewer) {
|
|
34536
|
-
super(viewer
|
|
34790
|
+
super(viewer);
|
|
34791
|
+
this.addPlaneX();
|
|
34537
34792
|
}
|
|
34538
34793
|
}
|
|
34539
34794
|
|
|
34540
34795
|
class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
|
|
34541
34796
|
constructor(viewer) {
|
|
34542
|
-
super(viewer
|
|
34797
|
+
super(viewer);
|
|
34798
|
+
this.addPlaneY();
|
|
34543
34799
|
}
|
|
34544
34800
|
}
|
|
34545
34801
|
|
|
34546
34802
|
class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
|
|
34547
34803
|
constructor(viewer) {
|
|
34548
|
-
super(viewer
|
|
34804
|
+
super(viewer);
|
|
34805
|
+
this.addPlaneZ();
|
|
34549
34806
|
}
|
|
34550
34807
|
}
|
|
34551
34808
|
|
|
@@ -34622,120 +34879,6 @@ void main() {
|
|
|
34622
34879
|
}
|
|
34623
34880
|
}
|
|
34624
34881
|
|
|
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
|
-
|
|
34739
34882
|
const _downPoint = new Vector2();
|
|
34740
34883
|
class MeasureLineDragger extends OrbitDragger {
|
|
34741
34884
|
constructor(viewer) {
|
|
@@ -35219,14 +35362,20 @@ void main() {
|
|
|
35219
35362
|
}
|
|
35220
35363
|
};
|
|
35221
35364
|
this.onKeyUp = (event) => {
|
|
35222
|
-
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
|
+
}
|
|
35223
35369
|
this.update();
|
|
35370
|
+
}
|
|
35224
35371
|
};
|
|
35225
35372
|
this.camera = camera;
|
|
35226
35373
|
this.groundObjects = groundObjects;
|
|
35227
35374
|
for (const obj of groundObjects) {
|
|
35228
35375
|
this._groundObjectBoxes.set(obj, new Box3().setFromObject(obj));
|
|
35229
35376
|
}
|
|
35377
|
+
const pos = this.object.position;
|
|
35378
|
+
this._rebuildGroundBox(pos);
|
|
35230
35379
|
this.raycaster = new Raycaster();
|
|
35231
35380
|
this.raycaster.near = 0;
|
|
35232
35381
|
this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
|
|
@@ -35835,6 +35984,7 @@ void main() {
|
|
|
35835
35984
|
draggers.registerDragger("Orbit", (viewer) => new OrbitDragger(viewer));
|
|
35836
35985
|
draggers.registerDragger("Zoom", (viewer) => new ZoomDragger(viewer));
|
|
35837
35986
|
draggers.registerDragger("MeasureLine", (viewer) => new MeasureLineDragger(viewer));
|
|
35987
|
+
draggers.registerDragger("CuttingPlane", (viewer) => new CuttingPlaneDragger(viewer));
|
|
35838
35988
|
draggers.registerDragger("CuttingPlaneXAxis", (viewer) => new CuttingPlaneXAxisDragger(viewer));
|
|
35839
35989
|
draggers.registerDragger("CuttingPlaneYAxis", (viewer) => new CuttingPlaneYAxisDragger(viewer));
|
|
35840
35990
|
draggers.registerDragger("CuttingPlaneZAxis", (viewer) => new CuttingPlaneZAxisDragger(viewer));
|
|
@@ -37369,7 +37519,7 @@ void main() {
|
|
|
37369
37519
|
this.getMousePosition(event, this.downPosition);
|
|
37370
37520
|
};
|
|
37371
37521
|
this.onPointerUp = (event) => {
|
|
37372
|
-
if (!event.isPrimary)
|
|
37522
|
+
if (!event.isPrimary || event.button !== 0)
|
|
37373
37523
|
return;
|
|
37374
37524
|
const upPosition = this.getMousePosition(event, new Vector2());
|
|
37375
37525
|
if (upPosition.distanceTo(this.downPosition) !== 0)
|
|
@@ -38832,6 +38982,81 @@ void main() {
|
|
|
38832
38982
|
this.mergedObjectMap = new Map();
|
|
38833
38983
|
this.mergedGeometryVisibility = new Map();
|
|
38834
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;
|
|
38835
39060
|
}
|
|
38836
39061
|
setVisibleEdges(visible) {
|
|
38837
39062
|
this.visibleEdges = visible;
|
|
@@ -39721,36 +39946,82 @@ void main() {
|
|
|
39721
39946
|
}
|
|
39722
39947
|
}
|
|
39723
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;
|
|
39724
39955
|
material.onBeforeCompile = (shader) => {
|
|
39956
|
+
shader.uniforms.transformTexture = uniforms.transformTexture;
|
|
39957
|
+
shader.uniforms.transformTextureSize = uniforms.transformTextureSize;
|
|
39725
39958
|
shader.vertexShader = shader.vertexShader.replace(
|
|
39726
39959
|
"#include <common>",
|
|
39727
39960
|
`
|
|
39728
39961
|
#include <common>
|
|
39962
|
+
|
|
39729
39963
|
attribute float visibility;
|
|
39964
|
+
attribute float objectId;
|
|
39730
39965
|
varying float vVisibility;
|
|
39731
|
-
|
|
39732
|
-
|
|
39733
|
-
|
|
39734
|
-
|
|
39735
|
-
|
|
39736
|
-
|
|
39737
|
-
|
|
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
|
+
}
|
|
39738
39983
|
`
|
|
39739
39984
|
);
|
|
39740
39985
|
shader.vertexShader = shader.vertexShader.replace(
|
|
39741
39986
|
"void main() {",
|
|
39742
39987
|
`
|
|
39743
39988
|
void main() {
|
|
39744
|
-
|
|
39989
|
+
mat4 batchingMatrix = getTransformMatrix(objectId);
|
|
39990
|
+
vVisibility = visibility;
|
|
39745
39991
|
`
|
|
39746
39992
|
);
|
|
39747
|
-
|
|
39748
|
-
|
|
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
|
+
shader.vertexShader = shader.vertexShader.replace(
|
|
40004
|
+
"#include <begin_vertex>",
|
|
39749
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
|
+
`
|
|
39750
40021
|
void main() {
|
|
39751
40022
|
if (vVisibility < 0.5) discard;
|
|
39752
40023
|
`
|
|
39753
|
-
|
|
40024
|
+
);
|
|
39754
40025
|
};
|
|
39755
40026
|
material.needsUpdate = true;
|
|
39756
40027
|
return material;
|
|
@@ -39865,6 +40136,8 @@ void main() {
|
|
|
39865
40136
|
this.objectIdToIndex.clear();
|
|
39866
40137
|
this.maxObjectId = 0;
|
|
39867
40138
|
this.objectVisibility = new Float32Array();
|
|
40139
|
+
this.meshToNodeMap = null;
|
|
40140
|
+
this.visibilityMaterials.clear();
|
|
39868
40141
|
}
|
|
39869
40142
|
setStructureTransform(structureId, matrix) {
|
|
39870
40143
|
const rootGroup = this.structureRoots.get(structureId);
|
|
@@ -39980,12 +40253,15 @@ void main() {
|
|
|
39980
40253
|
});
|
|
39981
40254
|
this.originalObjects.clear();
|
|
39982
40255
|
this.originalObjectsToSelection.clear();
|
|
40256
|
+
this.objectIdToIndex.clear();
|
|
40257
|
+
this.maxObjectId = 0;
|
|
39983
40258
|
const structureGroups = new Map();
|
|
39984
40259
|
this.dispatchEvent("optimizationprogress", {
|
|
39985
40260
|
phase: "collecting",
|
|
39986
40261
|
progress: 5,
|
|
39987
40262
|
message: "Collecting scene objects...",
|
|
39988
40263
|
});
|
|
40264
|
+
let totalObjectsToMerge = 0;
|
|
39989
40265
|
this.scene.traverse((object) => {
|
|
39990
40266
|
if (object.userData.structureId) {
|
|
39991
40267
|
const structureId = object.userData.structureId;
|
|
@@ -40003,17 +40279,32 @@ void main() {
|
|
|
40003
40279
|
});
|
|
40004
40280
|
}
|
|
40005
40281
|
const group = structureGroups.get(structureId);
|
|
40282
|
+
let added = false;
|
|
40006
40283
|
if (object instanceof Mesh) {
|
|
40007
40284
|
this.addToMaterialGroup(object, group.mapMeshes, group.meshes);
|
|
40285
|
+
added = true;
|
|
40008
40286
|
} else if (object instanceof LineSegments) {
|
|
40009
40287
|
this.addToMaterialGroup(object, group.mapLineSegments, group.lineSegments);
|
|
40288
|
+
added = true;
|
|
40010
40289
|
} else if (object instanceof Line$1) {
|
|
40011
40290
|
this.addToMaterialGroup(object, group.mapLines, group.lines);
|
|
40291
|
+
added = true;
|
|
40012
40292
|
} else if (object instanceof Points) {
|
|
40013
40293
|
this.addToMaterialGroup(object, group.mapPoints, group.points);
|
|
40294
|
+
added = true;
|
|
40295
|
+
}
|
|
40296
|
+
if (added) {
|
|
40297
|
+
totalObjectsToMerge++;
|
|
40014
40298
|
}
|
|
40015
40299
|
}
|
|
40016
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
|
+
}
|
|
40017
40308
|
let processedGroups = 0;
|
|
40018
40309
|
const totalGroups = structureGroups.size;
|
|
40019
40310
|
this.dispatchEvent("optimizationprogress", {
|
|
@@ -40058,7 +40349,6 @@ void main() {
|
|
|
40058
40349
|
this.originalObjectsToSelection.add(obj);
|
|
40059
40350
|
}
|
|
40060
40351
|
});
|
|
40061
|
-
this.initializeObjectVisibility();
|
|
40062
40352
|
console.log(`Optimization complete. Total objects: ${this.maxObjectId}`);
|
|
40063
40353
|
this.dispatchEvent("optimizationprogress", {
|
|
40064
40354
|
phase: "complete",
|
|
@@ -40127,6 +40417,7 @@ void main() {
|
|
|
40127
40417
|
}
|
|
40128
40418
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40129
40419
|
const mergedMesh = new Mesh(mergedGeometry, visibilityMaterial);
|
|
40420
|
+
mergedMesh.frustumCulled = false;
|
|
40130
40421
|
mergedMesh.userData.isOptimized = true;
|
|
40131
40422
|
rootGroup.add(mergedMesh);
|
|
40132
40423
|
this.mergedMesh.add(mergedMesh);
|
|
@@ -40243,6 +40534,7 @@ void main() {
|
|
|
40243
40534
|
geometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40244
40535
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40245
40536
|
const mergedLine = new LineSegments(geometry, visibilityMaterial);
|
|
40537
|
+
mergedLine.frustumCulled = false;
|
|
40246
40538
|
mergedLine.userData.isEdge = isEdge;
|
|
40247
40539
|
mergedLine.userData.isOptimized = true;
|
|
40248
40540
|
const mergedObjects = [mergedLine];
|
|
@@ -40331,6 +40623,7 @@ void main() {
|
|
|
40331
40623
|
mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
|
|
40332
40624
|
const visibilityMaterial = this.createVisibilityMaterial(group.material);
|
|
40333
40625
|
const mergedLine = new LineSegments(mergedGeometry, visibilityMaterial);
|
|
40626
|
+
mergedLine.frustumCulled = false;
|
|
40334
40627
|
mergedLine.userData.isEdge = isEdge;
|
|
40335
40628
|
mergedLine.userData.isOptimized = true;
|
|
40336
40629
|
if (this.useVAO) {
|
|
@@ -40400,7 +40693,27 @@ void main() {
|
|
|
40400
40693
|
const mergedObjects = [];
|
|
40401
40694
|
if (geometries.length > 0) {
|
|
40402
40695
|
const mergedGeometry = mergeGeometries(geometries, false);
|
|
40403
|
-
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;
|
|
40404
40717
|
mergedPoints.userData.isOptimized = true;
|
|
40405
40718
|
if (this.useVAO) {
|
|
40406
40719
|
this.createVAO(mergedPoints);
|
|
@@ -40469,13 +40782,33 @@ void main() {
|
|
|
40469
40782
|
geometriesWithIndex.push(clonedGeometry);
|
|
40470
40783
|
});
|
|
40471
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));
|
|
40472
40803
|
const material = new LineBasicMaterial({
|
|
40473
40804
|
vertexColors: true,
|
|
40474
40805
|
});
|
|
40806
|
+
const visibilityMaterial = this.createVisibilityMaterial(material);
|
|
40475
40807
|
if (this.useVAO) {
|
|
40476
40808
|
this.createVAO(finalGeometry);
|
|
40477
40809
|
}
|
|
40478
|
-
const mergedLine = new LineSegments(finalGeometry,
|
|
40810
|
+
const mergedLine = new LineSegments(finalGeometry, visibilityMaterial);
|
|
40811
|
+
mergedLine.frustumCulled = false;
|
|
40479
40812
|
mergedLine.userData.structureId = structureId;
|
|
40480
40813
|
mergedLine.userData.isOptimized = true;
|
|
40481
40814
|
rootGroup.add(mergedLine);
|
|
@@ -40594,18 +40927,50 @@ void main() {
|
|
|
40594
40927
|
console.warn("No merged objects to transform");
|
|
40595
40928
|
return;
|
|
40596
40929
|
}
|
|
40597
|
-
this.
|
|
40598
|
-
|
|
40599
|
-
|
|
40600
|
-
}
|
|
40601
|
-
for (const line of this.mergedLines) {
|
|
40602
|
-
this._applyTransformToMergedObject(line);
|
|
40930
|
+
if (!this.transformData) {
|
|
40931
|
+
console.warn("Transform texture not initialized");
|
|
40932
|
+
return;
|
|
40603
40933
|
}
|
|
40604
|
-
|
|
40605
|
-
|
|
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
|
+
}
|
|
40606
40965
|
}
|
|
40607
|
-
|
|
40608
|
-
this.
|
|
40966
|
+
if (textureNeedsUpdate) {
|
|
40967
|
+
this.updateTransformTexture();
|
|
40968
|
+
if (
|
|
40969
|
+
this._lastTransformTexture !== this.transformTexture ||
|
|
40970
|
+
this._lastTransformTextureSize !== this.transformTextureSize
|
|
40971
|
+
) {
|
|
40972
|
+
this.updateMaterialUniforms();
|
|
40973
|
+
}
|
|
40609
40974
|
}
|
|
40610
40975
|
}
|
|
40611
40976
|
createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
|
|
@@ -40622,21 +40987,66 @@ void main() {
|
|
|
40622
40987
|
? objects
|
|
40623
40988
|
: Array.from(objects)
|
|
40624
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
|
+
}
|
|
40625
40999
|
for (const obj of objectsArray) {
|
|
40626
41000
|
if (!obj.geometry || !obj.geometry.attributes.position) continue;
|
|
40627
|
-
|
|
40628
|
-
|
|
40629
|
-
|
|
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;
|
|
40630
41019
|
}
|
|
40631
|
-
|
|
40632
|
-
const
|
|
40633
|
-
boundingBox.getCenter(objectCenter);
|
|
40634
|
-
const direction = objectCenter.clone().sub(explodeCenter);
|
|
40635
|
-
const distance = direction.length();
|
|
41020
|
+
const explodeVector = obj.userData.explodeVector;
|
|
41021
|
+
const distance = explodeVector.length();
|
|
40636
41022
|
if (distance > 0) {
|
|
40637
|
-
|
|
40638
|
-
const
|
|
40639
|
-
|
|
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);
|
|
40640
41050
|
transformMap.set(obj, matrix);
|
|
40641
41051
|
}
|
|
40642
41052
|
}
|
|
@@ -40644,116 +41054,11 @@ void main() {
|
|
|
40644
41054
|
}
|
|
40645
41055
|
clearTransforms() {
|
|
40646
41056
|
this.objectTransforms.clear();
|
|
40647
|
-
|
|
40648
|
-
this._restoreOriginalGeometry(mesh);
|
|
40649
|
-
}
|
|
40650
|
-
for (const line of this.mergedLines) {
|
|
40651
|
-
this._restoreOriginalGeometry(line);
|
|
40652
|
-
}
|
|
40653
|
-
for (const lineSegment of this.mergedLineSegments) {
|
|
40654
|
-
this._restoreOriginalGeometry(lineSegment);
|
|
40655
|
-
}
|
|
40656
|
-
for (const point of this.mergedPoints) {
|
|
40657
|
-
this._restoreOriginalGeometry(point);
|
|
40658
|
-
}
|
|
41057
|
+
this._resetTransformData(true);
|
|
40659
41058
|
}
|
|
40660
41059
|
clearHandleTransforms() {
|
|
40661
41060
|
this.clearTransforms();
|
|
40662
41061
|
}
|
|
40663
|
-
_applyTransformToMergedObject(mergedObject) {
|
|
40664
|
-
const objectData = this.mergedObjectMap.get(mergedObject.uuid);
|
|
40665
|
-
if (!objectData || !objectData.objectMapping) return;
|
|
40666
|
-
const geometry = mergedObject.geometry;
|
|
40667
|
-
if (!geometry || !geometry.attributes.position) return;
|
|
40668
|
-
const positionAttr = geometry.attributes.position;
|
|
40669
|
-
const positions = positionAttr.array;
|
|
40670
|
-
if (!this.transformedGeometries.has(mergedObject.uuid)) {
|
|
40671
|
-
this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
|
|
40672
|
-
}
|
|
40673
|
-
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
40674
|
-
const tempVector = new Vector3();
|
|
40675
|
-
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
40676
|
-
const transform = this.objectTransforms.get(originalMesh);
|
|
40677
|
-
if (!transform) {
|
|
40678
|
-
const startIdx = mappingData.startVertexIndex * 3;
|
|
40679
|
-
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
40680
|
-
for (let i = startIdx; i < endIdx; i++) {
|
|
40681
|
-
positions[i] = originalPositions[i];
|
|
40682
|
-
}
|
|
40683
|
-
continue;
|
|
40684
|
-
}
|
|
40685
|
-
const startVertex = mappingData.startVertexIndex;
|
|
40686
|
-
const vertexCount = mappingData.vertexCount;
|
|
40687
|
-
for (let i = 0; i < vertexCount; i++) {
|
|
40688
|
-
const idx = (startVertex + i) * 3;
|
|
40689
|
-
tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
|
|
40690
|
-
tempVector.applyMatrix4(transform);
|
|
40691
|
-
positions[idx] = tempVector.x;
|
|
40692
|
-
positions[idx + 1] = tempVector.y;
|
|
40693
|
-
positions[idx + 2] = tempVector.z;
|
|
40694
|
-
}
|
|
40695
|
-
}
|
|
40696
|
-
if (geometry.attributes.normal) {
|
|
40697
|
-
this._updateNormalsForTransform(geometry, objectData, originalPositions);
|
|
40698
|
-
}
|
|
40699
|
-
positionAttr.needsUpdate = true;
|
|
40700
|
-
geometry.computeBoundingSphere();
|
|
40701
|
-
geometry.computeBoundingBox();
|
|
40702
|
-
}
|
|
40703
|
-
_updateNormalsForTransform(geometry, objectData, originalPositions) {
|
|
40704
|
-
const normalAttr = geometry.attributes.normal;
|
|
40705
|
-
if (!normalAttr) return;
|
|
40706
|
-
const normals = normalAttr.array;
|
|
40707
|
-
const tempVector = new Vector3();
|
|
40708
|
-
const normalMatrix = new Matrix4();
|
|
40709
|
-
const normalsKey = `${geometry.uuid}_normals`;
|
|
40710
|
-
if (!this.transformedGeometries.has(normalsKey)) {
|
|
40711
|
-
this.transformedGeometries.set(normalsKey, new Float32Array(normals));
|
|
40712
|
-
}
|
|
40713
|
-
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
40714
|
-
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
40715
|
-
const transform = this.objectTransforms.get(originalMesh);
|
|
40716
|
-
if (!transform) {
|
|
40717
|
-
const startIdx = mappingData.startVertexIndex * 3;
|
|
40718
|
-
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
40719
|
-
for (let i = startIdx; i < endIdx; i++) {
|
|
40720
|
-
normals[i] = originalNormals[i];
|
|
40721
|
-
}
|
|
40722
|
-
continue;
|
|
40723
|
-
}
|
|
40724
|
-
normalMatrix.copy(transform).invert().transpose();
|
|
40725
|
-
const startVertex = mappingData.startVertexIndex;
|
|
40726
|
-
const vertexCount = mappingData.vertexCount;
|
|
40727
|
-
for (let i = 0; i < vertexCount; i++) {
|
|
40728
|
-
const idx = (startVertex + i) * 3;
|
|
40729
|
-
tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
|
|
40730
|
-
tempVector.applyMatrix4(normalMatrix).normalize();
|
|
40731
|
-
normals[idx] = tempVector.x;
|
|
40732
|
-
normals[idx + 1] = tempVector.y;
|
|
40733
|
-
normals[idx + 2] = tempVector.z;
|
|
40734
|
-
}
|
|
40735
|
-
}
|
|
40736
|
-
normalAttr.needsUpdate = true;
|
|
40737
|
-
}
|
|
40738
|
-
_restoreOriginalGeometry(mergedObject) {
|
|
40739
|
-
const geometry = mergedObject.geometry;
|
|
40740
|
-
if (!geometry || !geometry.attributes.position) return;
|
|
40741
|
-
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
40742
|
-
if (originalPositions) {
|
|
40743
|
-
const positions = geometry.attributes.position.array;
|
|
40744
|
-
positions.set(originalPositions);
|
|
40745
|
-
geometry.attributes.position.needsUpdate = true;
|
|
40746
|
-
}
|
|
40747
|
-
const normalsKey = `${geometry.uuid}_normals`;
|
|
40748
|
-
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
40749
|
-
if (originalNormals && geometry.attributes.normal) {
|
|
40750
|
-
const normals = geometry.attributes.normal.array;
|
|
40751
|
-
normals.set(originalNormals);
|
|
40752
|
-
geometry.attributes.normal.needsUpdate = true;
|
|
40753
|
-
}
|
|
40754
|
-
geometry.computeBoundingSphere();
|
|
40755
|
-
geometry.computeBoundingBox();
|
|
40756
|
-
}
|
|
40757
41062
|
syncHiddenObjects() {
|
|
40758
41063
|
if (this.mergedObjectMap.size === 0) {
|
|
40759
41064
|
console.log("No merged objects to sync");
|