@inweb/viewer-three 27.2.0 → 27.2.2
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 +171 -60
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +168 -58
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/controls/WalkControls.d.ts +8 -0
- package/lib/Viewer/draggers/CuttingPlaneDragger.d.ts +9 -5
- package/lib/Viewer/helpers/PlaneHelper2.d.ts +8 -0
- package/package.json +5 -5
- package/src/Viewer/Viewer.ts +4 -0
- package/src/Viewer/components/CameraComponent.ts +1 -1
- package/src/Viewer/components/InfoComponent.ts +5 -1
- package/src/Viewer/controls/WalkControls.ts +41 -3
- package/src/Viewer/draggers/CuttingPlaneDragger.ts +65 -24
- package/src/Viewer/draggers/CuttingPlaneXAxis.ts +1 -1
- package/src/Viewer/draggers/CuttingPlaneYAxis.ts +1 -1
- package/src/Viewer/draggers/CuttingPlaneZAxis.ts +1 -1
- package/src/Viewer/helpers/{PlaneHelper.ts → PlaneHelper2.ts} +6 -23
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +68 -21
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +1 -0
- package/src/Viewer/models/ModelImpl.ts +1 -0
- package/lib/Viewer/helpers/PlaneHelper.d.ts +0 -11
package/dist/viewer-three.js
CHANGED
|
@@ -572,6 +572,7 @@
|
|
|
572
572
|
this.memory = {
|
|
573
573
|
geometries: 0,
|
|
574
574
|
geometryBytes: 0,
|
|
575
|
+
optimizedGeometryBytes: 0,
|
|
575
576
|
textures: 0,
|
|
576
577
|
textureBytes: 0,
|
|
577
578
|
materials: 0,
|
|
@@ -21254,7 +21255,7 @@
|
|
|
21254
21255
|
this.material.dispose();
|
|
21255
21256
|
}
|
|
21256
21257
|
}
|
|
21257
|
-
|
|
21258
|
+
class PlaneHelper extends Line$1 {
|
|
21258
21259
|
constructor( plane, size = 1, hex = 0xffff00 ) {
|
|
21259
21260
|
const color = hex;
|
|
21260
21261
|
const positions = [ 1, -1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
|
|
@@ -21284,7 +21285,7 @@
|
|
|
21284
21285
|
this.children[ 0 ].geometry.dispose();
|
|
21285
21286
|
this.children[ 0 ].material.dispose();
|
|
21286
21287
|
}
|
|
21287
|
-
}
|
|
21288
|
+
}
|
|
21288
21289
|
const _axis = new Vector3();
|
|
21289
21290
|
let _lineGeometry, _coneGeometry;
|
|
21290
21291
|
class ArrowHelper extends Object3D {
|
|
@@ -32454,7 +32455,7 @@ void main() {
|
|
|
32454
32455
|
PerspectiveCamera: PerspectiveCamera,
|
|
32455
32456
|
Plane: Plane,
|
|
32456
32457
|
PlaneGeometry: PlaneGeometry,
|
|
32457
|
-
PlaneHelper: PlaneHelper
|
|
32458
|
+
PlaneHelper: PlaneHelper,
|
|
32458
32459
|
PointLight: PointLight,
|
|
32459
32460
|
PointLightHelper: PointLightHelper,
|
|
32460
32461
|
Points: Points,
|
|
@@ -33643,17 +33644,15 @@ void main() {
|
|
|
33643
33644
|
}
|
|
33644
33645
|
}
|
|
33645
33646
|
|
|
33646
|
-
class
|
|
33647
|
-
constructor(
|
|
33647
|
+
class PlaneHelper2 extends Line$1 {
|
|
33648
|
+
constructor(size = 1, color = 0xc0c0c0) {
|
|
33648
33649
|
const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0];
|
|
33649
33650
|
const geometry = new BufferGeometry();
|
|
33650
33651
|
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
33651
33652
|
geometry.computeBoundingSphere();
|
|
33652
33653
|
super(geometry, new LineBasicMaterial({ color, toneMapped: false }));
|
|
33653
|
-
this.type = "
|
|
33654
|
-
this.plane = plane;
|
|
33654
|
+
this.type = "PlaneHelper2";
|
|
33655
33655
|
this.size = size;
|
|
33656
|
-
this.offset = offset;
|
|
33657
33656
|
const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
|
|
33658
33657
|
const geometry2 = new BufferGeometry();
|
|
33659
33658
|
geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
|
|
@@ -33671,14 +33670,10 @@ void main() {
|
|
|
33671
33670
|
dispose() {
|
|
33672
33671
|
this.geometry.dispose();
|
|
33673
33672
|
this.material.dispose();
|
|
33674
|
-
this.
|
|
33675
|
-
this.
|
|
33673
|
+
this.helper.geometry.dispose();
|
|
33674
|
+
this.helper.material.dispose();
|
|
33676
33675
|
}
|
|
33677
33676
|
updateMatrixWorld(force) {
|
|
33678
|
-
this.position.set(0, 0, 0);
|
|
33679
|
-
this.lookAt(this.plane.normal);
|
|
33680
|
-
this.position.copy(this.offset);
|
|
33681
|
-
this.translateZ(-(this.offset.dot(this.plane.normal) + this.plane.constant));
|
|
33682
33677
|
this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
|
|
33683
33678
|
super.updateMatrixWorld(force);
|
|
33684
33679
|
}
|
|
@@ -34434,26 +34429,41 @@ void main() {
|
|
|
34434
34429
|
}
|
|
34435
34430
|
|
|
34436
34431
|
class CuttingPlaneDragger extends OrbitDragger {
|
|
34437
|
-
constructor(viewer, normal
|
|
34432
|
+
constructor(viewer, normal) {
|
|
34438
34433
|
super(viewer);
|
|
34439
34434
|
this.transformChange = () => {
|
|
34435
|
+
this.plane.normal.copy(new Vector3(0, 0, -1)).applyQuaternion(this.planeCenter.quaternion);
|
|
34440
34436
|
this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
|
|
34441
34437
|
this.viewer.update();
|
|
34442
34438
|
};
|
|
34443
|
-
this.
|
|
34439
|
+
this.translateDrag = (event) => {
|
|
34444
34440
|
this.orbit.enabled = !event.value;
|
|
34441
|
+
this.rotate.enabled = !event.value;
|
|
34442
|
+
};
|
|
34443
|
+
this.rotateDrag = (event) => {
|
|
34444
|
+
this.orbit.enabled = !event.value;
|
|
34445
|
+
this.translate.enabled = !event.value;
|
|
34445
34446
|
};
|
|
34446
34447
|
this.updatePlaneSize = () => {
|
|
34447
34448
|
this.planeHelper.size = this.viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34448
34449
|
this.viewer.update();
|
|
34449
34450
|
};
|
|
34450
34451
|
this.updateTransformCamera = () => {
|
|
34451
|
-
this.
|
|
34452
|
+
this.translate.camera = this.viewer.camera;
|
|
34453
|
+
this.rotate.camera = this.viewer.camera;
|
|
34454
|
+
};
|
|
34455
|
+
this.onKeyDown = (event) => {
|
|
34456
|
+
if (event.key === "Shift")
|
|
34457
|
+
this.rotate.setRotationSnap(Math.PI / 4);
|
|
34458
|
+
};
|
|
34459
|
+
this.onKeyUp = (event) => {
|
|
34460
|
+
if (event.key === "Shift")
|
|
34461
|
+
this.rotate.setRotationSnap(null);
|
|
34452
34462
|
};
|
|
34453
34463
|
this.onDoubleClick = (event) => {
|
|
34454
34464
|
event.stopPropagation();
|
|
34455
|
-
this.
|
|
34456
|
-
this.
|
|
34465
|
+
this.planeCenter.rotateOnAxis(new Vector3(0, 1, 0), Math.PI);
|
|
34466
|
+
this.transformChange();
|
|
34457
34467
|
};
|
|
34458
34468
|
const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
|
|
34459
34469
|
const extentsCenter = viewer.extents.getCenter(new Vector3());
|
|
@@ -34462,24 +34472,38 @@ void main() {
|
|
|
34462
34472
|
if (!viewer.renderer.clippingPlanes)
|
|
34463
34473
|
viewer.renderer.clippingPlanes = [];
|
|
34464
34474
|
viewer.renderer.clippingPlanes.push(this.plane);
|
|
34465
|
-
this.planeHelper = new PlaneHelper(this.plane, extentsSize, color, extentsCenter);
|
|
34466
|
-
this.viewer.helpers.add(this.planeHelper);
|
|
34467
34475
|
this.planeCenter = new Object3D();
|
|
34468
34476
|
this.planeCenter.position.copy(extentsCenter);
|
|
34477
|
+
this.planeCenter.quaternion.setFromUnitVectors(new Vector3(0, 0, -1), normal);
|
|
34469
34478
|
this.viewer.helpers.add(this.planeCenter);
|
|
34470
|
-
this.
|
|
34471
|
-
this.
|
|
34472
|
-
this.
|
|
34473
|
-
this.
|
|
34474
|
-
this.
|
|
34475
|
-
this.
|
|
34476
|
-
this.
|
|
34477
|
-
this.
|
|
34479
|
+
this.planeHelper = new PlaneHelper2(extentsSize);
|
|
34480
|
+
this.planeCenter.add(this.planeHelper);
|
|
34481
|
+
this.translate = new TransformControls(viewer.camera, viewer.canvas);
|
|
34482
|
+
this.translate.setSpace("local");
|
|
34483
|
+
this.translate.showX = false;
|
|
34484
|
+
this.translate.showY = false;
|
|
34485
|
+
this.translate.showZ = true;
|
|
34486
|
+
this.translate.attach(this.planeCenter);
|
|
34487
|
+
this.translate.addEventListener("change", this.transformChange);
|
|
34488
|
+
this.translate.addEventListener("dragging-changed", this.translateDrag);
|
|
34489
|
+
this.viewer.helpers.add(this.translate.getHelper());
|
|
34490
|
+
this.rotate = new TransformControls(viewer.camera, viewer.canvas);
|
|
34491
|
+
this.rotate.setMode("rotate");
|
|
34492
|
+
this.rotate.setSpace("local");
|
|
34493
|
+
this.rotate.showX = true;
|
|
34494
|
+
this.rotate.showY = true;
|
|
34495
|
+
this.rotate.showZ = false;
|
|
34496
|
+
this.rotate.attach(this.planeCenter);
|
|
34497
|
+
this.rotate.addEventListener("change", this.transformChange);
|
|
34498
|
+
this.rotate.addEventListener("dragging-changed", this.rotateDrag);
|
|
34499
|
+
this.viewer.helpers.add(this.rotate.getHelper());
|
|
34478
34500
|
this.viewer.addEventListener("explode", this.updatePlaneSize);
|
|
34479
34501
|
this.viewer.addEventListener("show", this.updatePlaneSize);
|
|
34480
34502
|
this.viewer.addEventListener("showall", this.updatePlaneSize);
|
|
34481
34503
|
this.viewer.addEventListener("changecameramode", this.updateTransformCamera);
|
|
34482
34504
|
this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
|
|
34505
|
+
window.addEventListener("keydown", this.onKeyDown);
|
|
34506
|
+
window.addEventListener("keyup", this.onKeyUp);
|
|
34483
34507
|
this.viewer.update();
|
|
34484
34508
|
}
|
|
34485
34509
|
dispose() {
|
|
@@ -34488,11 +34512,18 @@ void main() {
|
|
|
34488
34512
|
this.viewer.removeEventListener("showall", this.updatePlaneSize);
|
|
34489
34513
|
this.viewer.removeEventListener("changecameramode", this.updateTransformCamera);
|
|
34490
34514
|
this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
|
|
34491
|
-
|
|
34492
|
-
|
|
34493
|
-
this.
|
|
34494
|
-
this.
|
|
34495
|
-
this.
|
|
34515
|
+
window.removeEventListener("keydown", this.onKeyDown);
|
|
34516
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
34517
|
+
this.translate.removeEventListener("change", this.transformChange);
|
|
34518
|
+
this.translate.removeEventListener("dragging-changed", this.translateDrag);
|
|
34519
|
+
this.translate.getHelper().removeFromParent();
|
|
34520
|
+
this.translate.detach();
|
|
34521
|
+
this.translate.dispose();
|
|
34522
|
+
this.rotate.removeEventListener("change", this.transformChange);
|
|
34523
|
+
this.rotate.removeEventListener("dragging-changed", this.rotateDrag);
|
|
34524
|
+
this.rotate.getHelper().removeFromParent();
|
|
34525
|
+
this.rotate.detach();
|
|
34526
|
+
this.rotate.dispose();
|
|
34496
34527
|
this.planeHelper.removeFromParent();
|
|
34497
34528
|
this.planeHelper.dispose();
|
|
34498
34529
|
this.planeCenter.removeFromParent();
|
|
@@ -34502,19 +34533,19 @@ void main() {
|
|
|
34502
34533
|
|
|
34503
34534
|
class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
|
|
34504
34535
|
constructor(viewer) {
|
|
34505
|
-
super(viewer, new Vector3(1, 0, 0)
|
|
34536
|
+
super(viewer, new Vector3(-1, 0, 0));
|
|
34506
34537
|
}
|
|
34507
34538
|
}
|
|
34508
34539
|
|
|
34509
34540
|
class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
|
|
34510
34541
|
constructor(viewer) {
|
|
34511
|
-
super(viewer, new Vector3(0, 1, 0)
|
|
34542
|
+
super(viewer, new Vector3(0, -1, 0));
|
|
34512
34543
|
}
|
|
34513
34544
|
}
|
|
34514
34545
|
|
|
34515
34546
|
class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
|
|
34516
34547
|
constructor(viewer) {
|
|
34517
|
-
super(viewer, new Vector3(0, 0, 1)
|
|
34548
|
+
super(viewer, new Vector3(0, 0, -1));
|
|
34518
34549
|
}
|
|
34519
34550
|
}
|
|
34520
34551
|
|
|
@@ -35116,6 +35147,12 @@ void main() {
|
|
|
35116
35147
|
this.movementSpeed = 0.1;
|
|
35117
35148
|
this.multiplier = 3;
|
|
35118
35149
|
this.groundFollowingSkippedFrames = 0;
|
|
35150
|
+
this.GROUND_BOX_HALF_SIZE = 20;
|
|
35151
|
+
this.GROUND_BOX_REFRESH_THRESHOLD = 0.3;
|
|
35152
|
+
this._groundObjectBoxes = new Map();
|
|
35153
|
+
this._activeGroundObjects = [];
|
|
35154
|
+
this._groundBox = new Box3();
|
|
35155
|
+
this._groundBoxCenter = new Vector3();
|
|
35119
35156
|
this.moveWheel = 0;
|
|
35120
35157
|
this.mouseDragOn = false;
|
|
35121
35158
|
this._up = new Vector3();
|
|
@@ -35187,6 +35224,9 @@ void main() {
|
|
|
35187
35224
|
};
|
|
35188
35225
|
this.camera = camera;
|
|
35189
35226
|
this.groundObjects = groundObjects;
|
|
35227
|
+
for (const obj of groundObjects) {
|
|
35228
|
+
this._groundObjectBoxes.set(obj, new Box3().setFromObject(obj));
|
|
35229
|
+
}
|
|
35190
35230
|
this.raycaster = new Raycaster();
|
|
35191
35231
|
this.raycaster.near = 0;
|
|
35192
35232
|
this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
|
|
@@ -35221,10 +35261,29 @@ void main() {
|
|
|
35221
35261
|
window.removeEventListener("keyup", this.onKeyUp);
|
|
35222
35262
|
super.dispose();
|
|
35223
35263
|
}
|
|
35264
|
+
_rebuildGroundBox(center) {
|
|
35265
|
+
const h = this.GROUND_BOX_HALF_SIZE;
|
|
35266
|
+
this._groundBoxCenter.copy(center);
|
|
35267
|
+
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));
|
|
35268
|
+
this._activeGroundObjects = this.groundObjects.filter((obj) => {
|
|
35269
|
+
const objectBox = this._groundObjectBoxes.get(obj);
|
|
35270
|
+
return objectBox !== undefined && this._groundBox.intersectsBox(objectBox);
|
|
35271
|
+
});
|
|
35272
|
+
}
|
|
35273
|
+
_needsGroundBoxRebuild(pos) {
|
|
35274
|
+
if (this._activeGroundObjects.length === 0 && this.groundObjects.length > 0)
|
|
35275
|
+
return true;
|
|
35276
|
+
const threshold = this.GROUND_BOX_HALF_SIZE * this.GROUND_BOX_REFRESH_THRESHOLD;
|
|
35277
|
+
return (Math.abs(pos.x - this._groundBoxCenter.x) > threshold || Math.abs(pos.z - this._groundBoxCenter.z) > threshold);
|
|
35278
|
+
}
|
|
35224
35279
|
updateGroundFollowing() {
|
|
35280
|
+
const pos = this.object.position;
|
|
35281
|
+
if (this._needsGroundBoxRebuild(pos)) {
|
|
35282
|
+
this._rebuildGroundBox(pos);
|
|
35283
|
+
}
|
|
35225
35284
|
this._up.copy(this.camera.up).negate();
|
|
35226
|
-
this.raycaster.set(
|
|
35227
|
-
const intersects = this.raycaster.intersectObjects(this.
|
|
35285
|
+
this.raycaster.set(pos, this._up);
|
|
35286
|
+
const intersects = this.raycaster.intersectObjects(this._activeGroundObjects, false);
|
|
35228
35287
|
if (intersects.length > 0) {
|
|
35229
35288
|
const groundY = intersects[0].point.y;
|
|
35230
35289
|
const targetY = groundY + this.EYE_HEIGHT;
|
|
@@ -36101,7 +36160,7 @@ void main() {
|
|
|
36101
36160
|
camera = object;
|
|
36102
36161
|
});
|
|
36103
36162
|
if (camera) {
|
|
36104
|
-
camera.isDefaultCamera = true;
|
|
36163
|
+
camera.userData.isDefaultCamera = true;
|
|
36105
36164
|
camera.scale.set(1, 1, 1);
|
|
36106
36165
|
this.switchCamera(camera);
|
|
36107
36166
|
const mode = this.getCameraMode(camera);
|
|
@@ -36305,6 +36364,7 @@ void main() {
|
|
|
36305
36364
|
this.viewer.info.optimizedScene.edges = 0;
|
|
36306
36365
|
this.viewer.info.memory.geometries = 0;
|
|
36307
36366
|
this.viewer.info.memory.geometryBytes = 0;
|
|
36367
|
+
this.viewer.info.memory.optimizedGeometryBytes = 0;
|
|
36308
36368
|
this.viewer.info.memory.textures = 0;
|
|
36309
36369
|
this.viewer.info.memory.textureBytes = 0;
|
|
36310
36370
|
this.viewer.info.memory.materials = 0;
|
|
@@ -36341,6 +36401,7 @@ void main() {
|
|
|
36341
36401
|
this.viewer.info.optimizedScene.edges += info.optimizedScene.edges;
|
|
36342
36402
|
this.viewer.info.memory.geometries += info.memory.geometries;
|
|
36343
36403
|
this.viewer.info.memory.geometryBytes += info.memory.geometryBytes;
|
|
36404
|
+
this.viewer.info.memory.optimizedGeometryBytes += info.memory.optimizedGeometryBytes;
|
|
36344
36405
|
this.viewer.info.memory.textures += info.memory.textures;
|
|
36345
36406
|
this.viewer.info.memory.textureBytes += info.memory.textureBytes;
|
|
36346
36407
|
this.viewer.info.memory.materials += info.memory.materials;
|
|
@@ -36351,7 +36412,9 @@ void main() {
|
|
|
36351
36412
|
this.viewer.info.performance.loadTime += performance.now() - this.startTime;
|
|
36352
36413
|
console.log("Number of objects:", info.scene.objects);
|
|
36353
36414
|
console.log("Number of objects after optimization:", info.optimizedScene.objects);
|
|
36354
|
-
console.log("
|
|
36415
|
+
console.log("Geometry size:", info.memory.geometryBytes / (1024 * 1024), "MB");
|
|
36416
|
+
console.log("Optimized geometry size:", info.memory.optimizedGeometryBytes / (1024 * 1024), "MB");
|
|
36417
|
+
console.log("Estimated GPU used:", info.memory.totalEstimatedGpuBytes / (1024 * 1024), "MB");
|
|
36355
36418
|
console.log("File load time:", this.viewer.info.performance.loadTime, "ms");
|
|
36356
36419
|
};
|
|
36357
36420
|
this.resize = () => {
|
|
@@ -37733,6 +37796,7 @@ void main() {
|
|
|
37733
37796
|
info.scene.edges = Math.floor(totalEdges);
|
|
37734
37797
|
info.memory.geometries = geometries.size;
|
|
37735
37798
|
info.memory.geometryBytes = geometryBytes;
|
|
37799
|
+
info.memory.optimizedGeometryBytes = 0;
|
|
37736
37800
|
info.memory.textures = textures.size;
|
|
37737
37801
|
info.memory.textureBytes = Math.floor(textureBytes);
|
|
37738
37802
|
info.memory.materials = materials.size;
|
|
@@ -37905,6 +37969,7 @@ void main() {
|
|
|
37905
37969
|
info.optimizedScene.edges = stats.scene.afterOptimization.edges;
|
|
37906
37970
|
info.memory.geometries = stats.memory.geometries.count;
|
|
37907
37971
|
info.memory.geometryBytes = stats.memory.geometries.bytes;
|
|
37972
|
+
info.memory.optimizedGeometryBytes = stats.memory.geometries.optimizedBytes;
|
|
37908
37973
|
info.memory.textures = stats.memory.textures.count;
|
|
37909
37974
|
info.memory.materials = stats.memory.materials.count;
|
|
37910
37975
|
info.memory.totalEstimatedGpuBytes = stats.memory.totalEstimatedGpuBytes;
|
|
@@ -38725,11 +38790,14 @@ void main() {
|
|
|
38725
38790
|
this.structures = [];
|
|
38726
38791
|
this.structureRoots = new Map();
|
|
38727
38792
|
this.memoryLimit = this.getAvailableMemory();
|
|
38793
|
+
this.optimizationMemoryMultiplier = 5;
|
|
38794
|
+
this.memoryEstimationFactor = 1.7;
|
|
38728
38795
|
this.loadedGeometrySize = 0;
|
|
38729
38796
|
this.geometryCache = new Map();
|
|
38730
38797
|
this.materialCache = new Map();
|
|
38731
38798
|
this.textureCache = new Map();
|
|
38732
38799
|
this.currentMemoryUsage = 0;
|
|
38800
|
+
this.pendingMemoryUsage = 0;
|
|
38733
38801
|
this.updateMemoryIndicator();
|
|
38734
38802
|
this.loadedMaterials = new Map();
|
|
38735
38803
|
this.abortController = new AbortController();
|
|
@@ -38785,7 +38853,7 @@ void main() {
|
|
|
38785
38853
|
} catch (error) {
|
|
38786
38854
|
console.warn("Error detecting available memory:", error);
|
|
38787
38855
|
}
|
|
38788
|
-
return memoryLimit
|
|
38856
|
+
return memoryLimit;
|
|
38789
38857
|
}
|
|
38790
38858
|
getAbortController() {
|
|
38791
38859
|
return this.abortController;
|
|
@@ -38793,9 +38861,26 @@ void main() {
|
|
|
38793
38861
|
abortLoading() {
|
|
38794
38862
|
this.abortController.abort();
|
|
38795
38863
|
}
|
|
38864
|
+
getOptimizedGeometrySize() {
|
|
38865
|
+
let total = 0;
|
|
38866
|
+
const addSize = (obj) => {
|
|
38867
|
+
if (obj && obj.geometry) total += this.estimateGeometrySize(obj);
|
|
38868
|
+
};
|
|
38869
|
+
this.mergedMesh?.forEach(addSize);
|
|
38870
|
+
this.mergedLines?.forEach(addSize);
|
|
38871
|
+
this.mergedLineSegments?.forEach(addSize);
|
|
38872
|
+
this.mergedPoints?.forEach(addSize);
|
|
38873
|
+
return total;
|
|
38874
|
+
}
|
|
38796
38875
|
updateMemoryIndicator() {
|
|
38876
|
+
const optimizedUsage = this.getOptimizedGeometrySize();
|
|
38877
|
+
const totalUsage = this.currentMemoryUsage + optimizedUsage;
|
|
38878
|
+
const totalUsageEstimate = Math.round(totalUsage * this.memoryEstimationFactor);
|
|
38797
38879
|
this.dispatchEvent("geometrymemory", {
|
|
38798
38880
|
currentUsage: this.currentMemoryUsage,
|
|
38881
|
+
optimizedUsage,
|
|
38882
|
+
totalUsage,
|
|
38883
|
+
totalUsageEstimate,
|
|
38799
38884
|
limit: this.memoryLimit,
|
|
38800
38885
|
});
|
|
38801
38886
|
}
|
|
@@ -38847,10 +38932,13 @@ void main() {
|
|
|
38847
38932
|
for (const geo of geometries) {
|
|
38848
38933
|
currentMemoryUsage += geo.size;
|
|
38849
38934
|
}
|
|
38850
|
-
|
|
38851
|
-
|
|
38935
|
+
const effectiveLimitForEviction = this.memoryLimit / this.memoryEstimationFactor;
|
|
38936
|
+
if (currentMemoryUsage > effectiveLimitForEviction) {
|
|
38937
|
+
console.log(
|
|
38938
|
+
`Memory usage (${Math.round((currentMemoryUsage * this.memoryEstimationFactor) / (1024 * 1024))}MB est.) exceeds limit`
|
|
38939
|
+
);
|
|
38852
38940
|
for (const geo of geometries) {
|
|
38853
|
-
if (currentMemoryUsage <=
|
|
38941
|
+
if (currentMemoryUsage <= effectiveLimitForEviction) break;
|
|
38854
38942
|
if (this.abortController.signal.aborted) {
|
|
38855
38943
|
throw new DOMException("Loading aborted", "AbortError");
|
|
38856
38944
|
}
|
|
@@ -38934,7 +39022,9 @@ void main() {
|
|
|
38934
39022
|
}
|
|
38935
39023
|
const materialCount = uniqueMaterialIds.size;
|
|
38936
39024
|
const textureCount = uniqueTextureIds.size;
|
|
38937
|
-
const
|
|
39025
|
+
const optimizedUsageBytes = this.getOptimizedGeometrySize();
|
|
39026
|
+
const totalUsageBytes = geometryMemoryBytes + optimizedUsageBytes;
|
|
39027
|
+
const estimatedGpuMemoryBytes = Math.round(totalUsageBytes * this.memoryEstimationFactor);
|
|
38938
39028
|
if (!this._webglInfoCache) {
|
|
38939
39029
|
try {
|
|
38940
39030
|
const gl = this.renderer.getContext();
|
|
@@ -38971,7 +39061,12 @@ void main() {
|
|
|
38971
39061
|
},
|
|
38972
39062
|
},
|
|
38973
39063
|
memory: {
|
|
38974
|
-
geometries: {
|
|
39064
|
+
geometries: {
|
|
39065
|
+
count: geometryCount,
|
|
39066
|
+
bytes: geometryMemoryBytes,
|
|
39067
|
+
optimizedBytes: optimizedUsageBytes,
|
|
39068
|
+
totalRawBytes: totalUsageBytes,
|
|
39069
|
+
},
|
|
38975
39070
|
textures: { count: textureCount },
|
|
38976
39071
|
materials: { count: materialCount },
|
|
38977
39072
|
totalEstimatedGpuBytes: estimatedGpuMemoryBytes,
|
|
@@ -38983,9 +39078,12 @@ void main() {
|
|
|
38983
39078
|
},
|
|
38984
39079
|
};
|
|
38985
39080
|
}
|
|
38986
|
-
async loadNode(nodeId, onLoadFinishCb) {
|
|
39081
|
+
async loadNode(nodeId, onLoadFinishCb, reservedEstimatedSize = 0) {
|
|
38987
39082
|
const node = this.nodes.get(nodeId);
|
|
38988
|
-
if (!node || node.loaded || node.loading)
|
|
39083
|
+
if (!node || node.loaded || node.loading) {
|
|
39084
|
+
this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
|
|
39085
|
+
return;
|
|
39086
|
+
}
|
|
38989
39087
|
node.loading = true;
|
|
38990
39088
|
const meshDef = node.structure.getJson().meshes[node.meshIndex];
|
|
38991
39089
|
try {
|
|
@@ -39068,6 +39166,7 @@ void main() {
|
|
|
39068
39166
|
if (bufferRequests.length === 0) {
|
|
39069
39167
|
node.loaded = true;
|
|
39070
39168
|
node.loading = false;
|
|
39169
|
+
this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
|
|
39071
39170
|
return;
|
|
39072
39171
|
}
|
|
39073
39172
|
bufferRequests.sort((a, b) => a.offset - b.offset);
|
|
@@ -39179,6 +39278,7 @@ void main() {
|
|
|
39179
39278
|
}
|
|
39180
39279
|
node.loaded = true;
|
|
39181
39280
|
node.loading = false;
|
|
39281
|
+
this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
|
|
39182
39282
|
const geometrySize = this.estimateGeometrySize(node.object);
|
|
39183
39283
|
this.geometryCache.set(node.object.uuid, geometrySize);
|
|
39184
39284
|
this.currentMemoryUsage += geometrySize;
|
|
@@ -39187,6 +39287,7 @@ void main() {
|
|
|
39187
39287
|
}
|
|
39188
39288
|
} catch (error) {
|
|
39189
39289
|
node.loading = false;
|
|
39290
|
+
this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
|
|
39190
39291
|
if (error.name === "AbortError") {
|
|
39191
39292
|
return;
|
|
39192
39293
|
}
|
|
@@ -39402,15 +39503,18 @@ void main() {
|
|
|
39402
39503
|
let loadedCount = 0;
|
|
39403
39504
|
let lastLoadedCount = 0;
|
|
39404
39505
|
const totalNodes = nodesToLoad.length;
|
|
39506
|
+
const progressTotal = { value: totalNodes };
|
|
39405
39507
|
const loadProgress = async () => {
|
|
39406
39508
|
loadedCount++;
|
|
39509
|
+
const total = progressTotal.value;
|
|
39510
|
+
const percentage = total > 0 ? Math.min(100, Math.round((loadedCount / total) * 100)) : 0;
|
|
39407
39511
|
if (loadedCount - lastLoadedCount > 1000) {
|
|
39408
39512
|
lastLoadedCount = loadedCount;
|
|
39409
39513
|
this.updateMemoryIndicator();
|
|
39410
39514
|
this.dispatchEvent("geometryprogress", {
|
|
39411
|
-
percentage
|
|
39515
|
+
percentage,
|
|
39412
39516
|
loaded: loadedCount,
|
|
39413
|
-
total
|
|
39517
|
+
total,
|
|
39414
39518
|
});
|
|
39415
39519
|
this.dispatchEvent("update");
|
|
39416
39520
|
await new Promise((resolve) => {
|
|
@@ -39420,20 +39524,22 @@ void main() {
|
|
|
39420
39524
|
};
|
|
39421
39525
|
try {
|
|
39422
39526
|
const loadOperations = [];
|
|
39527
|
+
let memoryLimitReached = false;
|
|
39423
39528
|
for (const nodeId of nodesToLoad) {
|
|
39424
39529
|
if (this.abortController.signal.aborted) {
|
|
39425
39530
|
throw new DOMException("Loading aborted", "AbortError");
|
|
39426
39531
|
}
|
|
39427
39532
|
const estimatedSize = await this.estimateNodeSize(nodeId);
|
|
39428
|
-
|
|
39429
|
-
|
|
39430
|
-
|
|
39431
|
-
|
|
39432
|
-
|
|
39433
|
-
|
|
39434
|
-
|
|
39533
|
+
const estimated = Number(estimatedSize) || 0;
|
|
39534
|
+
const effectiveLimit = this.memoryLimit / this.optimizationMemoryMultiplier / this.memoryEstimationFactor;
|
|
39535
|
+
if (this.currentMemoryUsage + this.pendingMemoryUsage + estimated > effectiveLimit) {
|
|
39536
|
+
memoryLimitReached = true;
|
|
39537
|
+
progressTotal.value = loadOperations.length;
|
|
39538
|
+
console.log(`Memory limit reached after scheduling ${loadOperations.length} nodes`);
|
|
39539
|
+
break;
|
|
39435
39540
|
}
|
|
39436
|
-
|
|
39541
|
+
this.pendingMemoryUsage += estimated;
|
|
39542
|
+
loadOperations.push(this.loadNode(nodeId, loadProgress, estimated));
|
|
39437
39543
|
}
|
|
39438
39544
|
for (const structure of this.structures) {
|
|
39439
39545
|
loadOperations.push(structure.flushBufferRequests());
|
|
@@ -39441,7 +39547,8 @@ void main() {
|
|
|
39441
39547
|
await Promise.all(loadOperations);
|
|
39442
39548
|
this.dispatchEvent("geometryend", {
|
|
39443
39549
|
totalLoaded: loadedCount,
|
|
39444
|
-
totalNodes,
|
|
39550
|
+
totalNodes: progressTotal.value,
|
|
39551
|
+
memoryLimitReached,
|
|
39445
39552
|
});
|
|
39446
39553
|
return loadedCount;
|
|
39447
39554
|
} catch (error) {
|
|
@@ -39751,6 +39858,7 @@ void main() {
|
|
|
39751
39858
|
this.transformedGeometries.clear();
|
|
39752
39859
|
this.totalLoadedObjects = 0;
|
|
39753
39860
|
this.currentMemoryUsage = 0;
|
|
39861
|
+
this.pendingMemoryUsage = 0;
|
|
39754
39862
|
this.loadedGeometrySize = 0;
|
|
39755
39863
|
this.abortController = new AbortController();
|
|
39756
39864
|
this.updateMemoryIndicator();
|
|
@@ -39957,6 +40065,7 @@ void main() {
|
|
|
39957
40065
|
progress: 100,
|
|
39958
40066
|
message: `Optimization complete! ${this.maxObjectId} objects processed.`,
|
|
39959
40067
|
});
|
|
40068
|
+
this.updateMemoryIndicator();
|
|
39960
40069
|
this.dispatchEvent("update");
|
|
39961
40070
|
}
|
|
39962
40071
|
async mergeMeshGroups(materialGroups, rootGroup) {
|
|
@@ -57695,12 +57804,14 @@ js: import "konva/skia-backend";
|
|
|
57695
57804
|
if (!this.renderer)
|
|
57696
57805
|
return;
|
|
57697
57806
|
this._markup.clearOverlay();
|
|
57807
|
+
this.emitEvent({ type: "clearoverlay" });
|
|
57698
57808
|
this.update();
|
|
57699
57809
|
}
|
|
57700
57810
|
clearSlices() {
|
|
57701
57811
|
if (!this.renderer)
|
|
57702
57812
|
return;
|
|
57703
57813
|
this.renderer.clippingPlanes = [];
|
|
57814
|
+
this.emitEvent({ type: "clearslices" });
|
|
57704
57815
|
this.update();
|
|
57705
57816
|
}
|
|
57706
57817
|
getSelected() {
|