@inweb/viewer-three 26.7.6 → 26.8.0
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 +367 -230
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +4 -2
- package/dist/viewer-three.module.js +335 -159
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/components/HighlighterComponent.d.ts +2 -2
- package/lib/Viewer/loaders/GLTFCloudDynamicLoader.d.ts +0 -2
- package/lib/Viewer/loaders/index.d.ts +1 -1
- package/package.json +5 -5
- package/src/Viewer/commands/SetSelected.ts +1 -0
- package/src/Viewer/commands/index.ts +1 -1
- package/src/Viewer/components/HighlighterComponent.ts +38 -16
- package/src/Viewer/components/LightComponent.ts +11 -15
- package/src/Viewer/components/SelectionComponent.ts +1 -2
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +187 -65
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +7 -12
- package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +120 -114
- package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +7 -13
- package/src/Viewer/loaders/index.ts +1 -1
package/dist/viewer-three.js
CHANGED
|
@@ -59894,6 +59894,7 @@ void main() {
|
|
|
59894
59894
|
selection.clearSelection();
|
|
59895
59895
|
viewer.models.forEach((model) => {
|
|
59896
59896
|
const objects = model.getObjectsByHandles(handles);
|
|
59897
|
+
model.showObjects(objects);
|
|
59897
59898
|
selection.select(objects, model);
|
|
59898
59899
|
});
|
|
59899
59900
|
viewer.update();
|
|
@@ -60074,9 +60075,9 @@ void main() {
|
|
|
60074
60075
|
commands.registerCommand("clearMarkup", clearMarkup);
|
|
60075
60076
|
commands.registerCommand("clearSelected", clearSelected);
|
|
60076
60077
|
commands.registerCommand("clearSlices", clearSlices);
|
|
60078
|
+
commands.registerCommand("collect", collect);
|
|
60077
60079
|
commands.registerCommand("createPreview", createPreview);
|
|
60078
60080
|
commands.registerCommand("explode", explode);
|
|
60079
|
-
commands.registerCommand("collect", collect);
|
|
60080
60081
|
commands.registerCommand("getDefaultViewPositions", getDefaultViewPositions);
|
|
60081
60082
|
commands.registerCommand("getModels", getModels);
|
|
60082
60083
|
commands.registerCommand("getSelected", getSelected);
|
|
@@ -60309,30 +60310,29 @@ void main() {
|
|
|
60309
60310
|
const extentsCenter = this.viewer.extents.getCenter(new Vector3());
|
|
60310
60311
|
const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius;
|
|
60311
60312
|
this.directionalLight.position
|
|
60312
|
-
.set(0.5, 0, 0
|
|
60313
|
+
.set(0.5, 0.866, 0) // ~60º
|
|
60313
60314
|
.multiplyScalar(extentsSize * 2)
|
|
60314
60315
|
.add(extentsCenter);
|
|
60315
60316
|
this.directionalLight.target.position.copy(extentsCenter);
|
|
60316
|
-
this.frontLight.position
|
|
60317
|
+
this.frontLight.position
|
|
60318
|
+
.set(0, 0, 1)
|
|
60319
|
+
.multiplyScalar(extentsSize * 2)
|
|
60320
|
+
.add(extentsCenter);
|
|
60317
60321
|
this.frontLight.target.position.copy(extentsCenter);
|
|
60318
|
-
this.hemisphereLight.position
|
|
60322
|
+
this.hemisphereLight.position
|
|
60323
|
+
.set(0, 0, 1)
|
|
60324
|
+
.multiplyScalar(extentsSize * 3)
|
|
60325
|
+
.add(extentsCenter);
|
|
60319
60326
|
this.viewer.scene.add(this.ambientLight);
|
|
60320
60327
|
this.viewer.scene.add(this.directionalLight);
|
|
60321
60328
|
this.viewer.scene.add(this.frontLight);
|
|
60322
60329
|
this.viewer.scene.add(this.hemisphereLight);
|
|
60323
60330
|
};
|
|
60324
60331
|
this.viewer = viewer;
|
|
60325
|
-
this.ambientLight = new AmbientLight(0xffffff, 1);
|
|
60326
|
-
this.
|
|
60327
|
-
this.directionalLight = new DirectionalLight(0xffffff, 1);
|
|
60328
|
-
this.directionalLight.position.set(0.5, 0, 0.866); // ~60º
|
|
60329
|
-
this.viewer.scene.add(this.directionalLight);
|
|
60332
|
+
this.ambientLight = new AmbientLight(0xffffff, 1.0);
|
|
60333
|
+
this.directionalLight = new DirectionalLight(0xffffff, 1.0);
|
|
60330
60334
|
this.frontLight = new DirectionalLight(0xffffff, 1.25);
|
|
60331
|
-
this.frontLight.position.set(0, 1, 0);
|
|
60332
|
-
this.viewer.scene.add(this.frontLight);
|
|
60333
60335
|
this.hemisphereLight = new HemisphereLight(0xffffff, 0x444444, 1.25);
|
|
60334
|
-
this.hemisphereLight.position.set(0, 0, 1);
|
|
60335
|
-
this.viewer.scene.add(this.hemisphereLight);
|
|
60336
60336
|
this.viewer.addEventListener("databasechunk", this.geometryEnd);
|
|
60337
60337
|
this.viewer.addEventListener("clear", this.geometryEnd);
|
|
60338
60338
|
}
|
|
@@ -61430,19 +61430,25 @@ void main() {
|
|
|
61430
61430
|
class HighlighterComponent {
|
|
61431
61431
|
constructor(viewer) {
|
|
61432
61432
|
this.geometryEnd = () => {
|
|
61433
|
-
const { facesColor, facesTransparancy, edgesColor } = this.viewer.options;
|
|
61434
|
-
this.highlightMaterial = new
|
|
61433
|
+
const { facesColor, facesTransparancy, edgesColor, edgesOverlap, facesOverlap } = this.viewer.options;
|
|
61434
|
+
this.highlightMaterial = new MeshPhongMaterial({
|
|
61435
61435
|
color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
|
|
61436
61436
|
transparent: true,
|
|
61437
61437
|
opacity: (255 - facesTransparancy) / 255,
|
|
61438
|
-
depthTest:
|
|
61439
|
-
depthWrite:
|
|
61438
|
+
depthTest: !facesOverlap,
|
|
61439
|
+
depthWrite: !facesOverlap,
|
|
61440
|
+
specular: 0x222222,
|
|
61441
|
+
shininess: 10,
|
|
61442
|
+
reflectivity: 0.05,
|
|
61443
|
+
polygonOffset: true,
|
|
61444
|
+
polygonOffsetFactor: 1,
|
|
61445
|
+
polygonOffsetUnits: 1,
|
|
61440
61446
|
});
|
|
61441
61447
|
this.outlineMaterial = new LineMaterial({
|
|
61442
61448
|
color: new Color(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255),
|
|
61443
61449
|
linewidth: 1.5,
|
|
61444
|
-
depthTest:
|
|
61445
|
-
depthWrite:
|
|
61450
|
+
depthTest: !edgesOverlap,
|
|
61451
|
+
depthWrite: !edgesOverlap,
|
|
61446
61452
|
resolution: new Vector2(window.innerWidth, window.innerHeight),
|
|
61447
61453
|
});
|
|
61448
61454
|
this.highlightLineMaterial = new LineBasicMaterial({
|
|
@@ -61455,18 +61461,27 @@ void main() {
|
|
|
61455
61461
|
linewidth: 5,
|
|
61456
61462
|
transparent: true,
|
|
61457
61463
|
opacity: 0.8,
|
|
61458
|
-
depthTest:
|
|
61459
|
-
depthWrite:
|
|
61464
|
+
depthTest: !edgesOverlap,
|
|
61465
|
+
depthWrite: !edgesOverlap,
|
|
61460
61466
|
resolution: new Vector2(window.innerWidth, window.innerHeight),
|
|
61461
61467
|
});
|
|
61462
61468
|
};
|
|
61463
61469
|
this.optionsChange = () => {
|
|
61464
|
-
const { facesColor, facesTransparancy, edgesColor } = this.viewer.options;
|
|
61470
|
+
const { facesColor, facesTransparancy, edgesColor, edgesVisibility, edgesOverlap, facesOverlap } = this.viewer.options;
|
|
61465
61471
|
this.highlightMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
61466
61472
|
this.highlightMaterial.opacity = (255 - facesTransparancy) / 255;
|
|
61473
|
+
this.highlightMaterial.depthTest = !facesOverlap;
|
|
61474
|
+
this.highlightMaterial.depthWrite = !facesOverlap;
|
|
61467
61475
|
this.outlineMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
|
|
61476
|
+
this.outlineMaterial.depthTest = !edgesOverlap;
|
|
61477
|
+
this.outlineMaterial.depthWrite = !edgesOverlap;
|
|
61468
61478
|
this.highlightLineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
61469
61479
|
this.highlightLineGlowMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
61480
|
+
this.viewer.selected.forEach((selected) => {
|
|
61481
|
+
const wireframe = selected.userData.highlightWireframe;
|
|
61482
|
+
if (wireframe)
|
|
61483
|
+
wireframe.visible = edgesVisibility;
|
|
61484
|
+
});
|
|
61470
61485
|
this.viewer.update();
|
|
61471
61486
|
};
|
|
61472
61487
|
this.viewer = viewer;
|
|
@@ -61491,6 +61506,7 @@ void main() {
|
|
|
61491
61506
|
this.viewer.removeEventListener("resize", this.viewerResize);
|
|
61492
61507
|
}
|
|
61493
61508
|
highlight(objects) {
|
|
61509
|
+
const { edgesVisibility } = this.viewer.options;
|
|
61494
61510
|
if (!Array.isArray(objects))
|
|
61495
61511
|
objects = [objects];
|
|
61496
61512
|
if (!objects.length)
|
|
@@ -61508,21 +61524,23 @@ void main() {
|
|
|
61508
61524
|
wireframe.position.copy(object.position);
|
|
61509
61525
|
wireframe.rotation.copy(object.rotation);
|
|
61510
61526
|
wireframe.scale.copy(object.scale);
|
|
61527
|
+
wireframe.visible = edgesVisibility;
|
|
61511
61528
|
object.parent.add(wireframe);
|
|
61512
|
-
object.userData.
|
|
61529
|
+
object.userData.highlightWireframe = wireframe;
|
|
61513
61530
|
object.userData.originalMaterial = object.material;
|
|
61514
61531
|
object.material = this.highlightLineMaterial;
|
|
61515
61532
|
object.isHighlighted = true;
|
|
61516
61533
|
}
|
|
61517
61534
|
else if (object.isMesh) {
|
|
61518
|
-
const edgesGeometry = new EdgesGeometry(object.geometry,
|
|
61535
|
+
const edgesGeometry = new EdgesGeometry(object.geometry, 60);
|
|
61519
61536
|
const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
|
|
61520
61537
|
const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
|
|
61521
61538
|
wireframe.position.copy(object.position);
|
|
61522
61539
|
wireframe.rotation.copy(object.rotation);
|
|
61523
61540
|
wireframe.scale.copy(object.scale);
|
|
61541
|
+
wireframe.visible = edgesVisibility;
|
|
61524
61542
|
object.parent.add(wireframe);
|
|
61525
|
-
object.userData.
|
|
61543
|
+
object.userData.highlightWireframe = wireframe;
|
|
61526
61544
|
object.userData.originalMaterial = object.material;
|
|
61527
61545
|
object.material = this.highlightMaterial;
|
|
61528
61546
|
object.isHighlighted = true;
|
|
@@ -61539,9 +61557,9 @@ void main() {
|
|
|
61539
61557
|
return;
|
|
61540
61558
|
object.isHighlighted = false;
|
|
61541
61559
|
object.material = object.userData.originalMaterial;
|
|
61542
|
-
object.userData.
|
|
61560
|
+
object.userData.highlightWireframe.removeFromParent();
|
|
61543
61561
|
delete object.userData.originalMaterial;
|
|
61544
|
-
delete object.userData.
|
|
61562
|
+
delete object.userData.highlightWireframe;
|
|
61545
61563
|
});
|
|
61546
61564
|
}
|
|
61547
61565
|
viewerResize(event) {
|
|
@@ -61590,7 +61608,8 @@ void main() {
|
|
|
61590
61608
|
this.viewer.models.forEach((model) => {
|
|
61591
61609
|
const objects = model.getVisibleObjects();
|
|
61592
61610
|
const intersects = this.getPointerIntersects(upPosition, objects);
|
|
61593
|
-
|
|
61611
|
+
if (intersects.length > 0)
|
|
61612
|
+
intersections.push({ ...intersects[0], model });
|
|
61594
61613
|
});
|
|
61595
61614
|
intersections = intersections.sort((a, b) => a.distance - b.distance);
|
|
61596
61615
|
if (!event.shiftKey)
|
|
@@ -61657,7 +61676,6 @@ void main() {
|
|
|
61657
61676
|
objects = [objects];
|
|
61658
61677
|
if (!objects.length)
|
|
61659
61678
|
return;
|
|
61660
|
-
model.showObjects(objects);
|
|
61661
61679
|
model.showOriginalObjects(objects);
|
|
61662
61680
|
this.highlighter.highlight(objects);
|
|
61663
61681
|
objects.forEach((object) => this.viewer.selected.push(object));
|
|
@@ -67313,10 +67331,8 @@ void main() {
|
|
|
67313
67331
|
return objects;
|
|
67314
67332
|
}
|
|
67315
67333
|
hideObjects(objects) {
|
|
67316
|
-
this.
|
|
67317
|
-
|
|
67318
|
-
.forEach((handle) => this.gltfLoader.hiddenHandles.add(handle));
|
|
67319
|
-
this.gltfLoader.syncHiddenObjects();
|
|
67334
|
+
const handles = this.getHandlesByObjects(objects);
|
|
67335
|
+
this.gltfLoader.hideObjects(handles);
|
|
67320
67336
|
return this;
|
|
67321
67337
|
}
|
|
67322
67338
|
isolateObjects(objects) {
|
|
@@ -67325,23 +67341,20 @@ void main() {
|
|
|
67325
67341
|
return this;
|
|
67326
67342
|
}
|
|
67327
67343
|
showObjects(objects) {
|
|
67328
|
-
this.
|
|
67329
|
-
|
|
67330
|
-
.forEach((handle) => this.gltfLoader.hiddenHandles.delete(handle));
|
|
67331
|
-
this.gltfLoader.syncHiddenObjects();
|
|
67344
|
+
const handles = this.getHandlesByObjects(objects);
|
|
67345
|
+
this.gltfLoader.showObjects(handles);
|
|
67332
67346
|
return this;
|
|
67333
67347
|
}
|
|
67334
67348
|
showAllObjects() {
|
|
67335
|
-
this.gltfLoader.
|
|
67336
|
-
this.gltfLoader.syncHiddenObjects();
|
|
67349
|
+
this.gltfLoader.showAllHiddenObjects();
|
|
67337
67350
|
return this;
|
|
67338
67351
|
}
|
|
67339
67352
|
showOriginalObjects(objects) {
|
|
67340
|
-
this.
|
|
67353
|
+
this.gltfLoader.showOriginalObjects(objects);
|
|
67341
67354
|
return this;
|
|
67342
67355
|
}
|
|
67343
67356
|
hideOriginalObjects(objects) {
|
|
67344
|
-
this.
|
|
67357
|
+
this.gltfLoader.hideOriginalObjects(objects);
|
|
67345
67358
|
return this;
|
|
67346
67359
|
}
|
|
67347
67360
|
}
|
|
@@ -67364,24 +67377,20 @@ void main() {
|
|
|
67364
67377
|
TRIANGLE_STRIP: 5,
|
|
67365
67378
|
TRIANGLE_FAN: 6};
|
|
67366
67379
|
|
|
67380
|
+
const MAX_GAP = 128 * 1024; // 128 KB
|
|
67381
|
+
const MAX_CHUNK = 30 * 1024 * 1024; // 100 MB
|
|
67382
|
+
|
|
67367
67383
|
class GltfStructure {
|
|
67368
67384
|
constructor(id) {
|
|
67369
67385
|
this.id = `${id}`;
|
|
67370
67386
|
this.json = null;
|
|
67371
67387
|
this.baseUrl = "";
|
|
67372
|
-
|
|
67373
|
-
// Binary manager properties
|
|
67374
67388
|
this.loadController = null;
|
|
67375
|
-
// Request batching parameters
|
|
67376
67389
|
this.batchDelay = 10;
|
|
67377
67390
|
this.maxBatchSize = 5 * 1024 * 1024;
|
|
67378
67391
|
this.maxRangesPerRequest = 512;
|
|
67379
|
-
|
|
67380
|
-
// Request queue
|
|
67381
67392
|
this.pendingRequests = [];
|
|
67382
67393
|
this.batchTimeout = null;
|
|
67383
|
-
|
|
67384
|
-
// Material and texture properties
|
|
67385
67394
|
this.textureLoader = new TextureLoader();
|
|
67386
67395
|
this.materials = new Map();
|
|
67387
67396
|
this.textureCache = new Map();
|
|
@@ -67413,57 +67422,110 @@ void main() {
|
|
|
67413
67422
|
return this.json;
|
|
67414
67423
|
}
|
|
67415
67424
|
|
|
67416
|
-
// Schedule a request for processing
|
|
67417
67425
|
scheduleRequest(request) {
|
|
67418
|
-
this.pendingRequests.push(request);
|
|
67419
|
-
|
|
67420
|
-
// Clear existing timeout
|
|
67421
|
-
if (this.batchTimeout) {
|
|
67422
|
-
clearTimeout(this.batchTimeout);
|
|
67423
|
-
}
|
|
67424
|
-
|
|
67425
|
-
// Set new timeout for batch processing
|
|
67426
|
-
this.batchTimeout = setTimeout(() => this.processBatch(), this.batchDelay);
|
|
67427
|
-
|
|
67428
|
-
// Return a promise that will resolve when the data is available
|
|
67429
67426
|
return new Promise((resolve, reject) => {
|
|
67430
|
-
|
|
67431
|
-
|
|
67427
|
+
this.pendingRequests.push({
|
|
67428
|
+
...request,
|
|
67429
|
+
_resolve: resolve,
|
|
67430
|
+
_reject: reject,
|
|
67431
|
+
});
|
|
67432
67432
|
});
|
|
67433
67433
|
}
|
|
67434
67434
|
|
|
67435
|
-
async
|
|
67436
|
-
if (this.pendingRequests.length === 0) return;
|
|
67437
|
-
|
|
67438
|
-
// Take current batch of requests and clear timeout
|
|
67439
|
-
const currentBatch = [...this.pendingRequests];
|
|
67435
|
+
async flushBufferRequests() {
|
|
67436
|
+
if (!this.pendingRequests || this.pendingRequests.length === 0) return;
|
|
67437
|
+
const requests = [...this.pendingRequests];
|
|
67440
67438
|
this.pendingRequests = [];
|
|
67441
67439
|
|
|
67442
|
-
|
|
67443
|
-
|
|
67444
|
-
|
|
67440
|
+
requests.sort((a, b) => a.offset - b.offset);
|
|
67441
|
+
const mergedRanges = [];
|
|
67442
|
+
let current = {
|
|
67443
|
+
start: requests[0].offset,
|
|
67444
|
+
end: requests[0].offset + requests[0].length,
|
|
67445
|
+
requests: [requests[0]],
|
|
67446
|
+
};
|
|
67447
|
+
for (let i = 1; i < requests.length; i++) {
|
|
67448
|
+
const req = requests[i];
|
|
67449
|
+
const gap = req.offset - current.end;
|
|
67450
|
+
const newEnd = Math.max(current.end, req.offset + req.length);
|
|
67451
|
+
const projectedSize = newEnd - current.start;
|
|
67452
|
+
if (gap <= MAX_GAP && projectedSize <= MAX_CHUNK) {
|
|
67453
|
+
current.end = newEnd;
|
|
67454
|
+
current.requests.push(req);
|
|
67455
|
+
} else {
|
|
67456
|
+
mergedRanges.push(current);
|
|
67457
|
+
current = {
|
|
67458
|
+
start: req.offset,
|
|
67459
|
+
end: req.offset + req.length,
|
|
67460
|
+
requests: [req],
|
|
67461
|
+
};
|
|
67462
|
+
}
|
|
67445
67463
|
}
|
|
67446
|
-
|
|
67447
|
-
|
|
67448
|
-
|
|
67449
|
-
|
|
67450
|
-
|
|
67451
|
-
|
|
67452
|
-
let
|
|
67453
|
-
|
|
67454
|
-
|
|
67455
|
-
|
|
67456
|
-
|
|
67464
|
+
mergedRanges.push(current);
|
|
67465
|
+
const finalRanges = [];
|
|
67466
|
+
for (const range of mergedRanges) {
|
|
67467
|
+
let { start, end, requests } = range;
|
|
67468
|
+
while (end - start > MAX_CHUNK) {
|
|
67469
|
+
let splitIdx = 0;
|
|
67470
|
+
for (let i = 0; i < requests.length; i++) {
|
|
67471
|
+
if (requests[i].offset + requests[i].length - start > MAX_CHUNK) {
|
|
67472
|
+
break;
|
|
67473
|
+
}
|
|
67474
|
+
splitIdx = i;
|
|
67475
|
+
}
|
|
67476
|
+
const chunkRequests = requests.slice(0, splitIdx + 1);
|
|
67477
|
+
const chunkEnd =
|
|
67478
|
+
chunkRequests[chunkRequests.length - 1].offset + chunkRequests[chunkRequests.length - 1].length;
|
|
67479
|
+
finalRanges.push({
|
|
67480
|
+
start,
|
|
67481
|
+
end: chunkEnd,
|
|
67482
|
+
requests: chunkRequests,
|
|
67457
67483
|
});
|
|
67484
|
+
requests = requests.slice(splitIdx + 1);
|
|
67485
|
+
if (requests.length > 0) {
|
|
67486
|
+
start = requests[0].offset;
|
|
67487
|
+
end = requests[0].offset + requests[0].length;
|
|
67488
|
+
for (let i = 1; i < requests.length; i++) {
|
|
67489
|
+
end = Math.max(end, requests[i].offset + requests[i].length);
|
|
67490
|
+
}
|
|
67491
|
+
}
|
|
67492
|
+
}
|
|
67493
|
+
if (requests.length > 0) {
|
|
67494
|
+
finalRanges.push({ start, end, requests });
|
|
67458
67495
|
}
|
|
67459
|
-
} catch (error) {
|
|
67460
|
-
console.error("Error processing batch:", error);
|
|
67461
|
-
currentBatch.forEach((request) => request.reject(error));
|
|
67462
67496
|
}
|
|
67463
|
-
|
|
67464
|
-
|
|
67465
|
-
|
|
67497
|
+
/*
|
|
67498
|
+
for (const range of finalRanges) {
|
|
67499
|
+
const length = range.end - range.start;
|
|
67500
|
+
const buffer = await this.loadController.loadBinaryData([
|
|
67501
|
+
{ offset: range.start, length: length }
|
|
67502
|
+
]);
|
|
67503
|
+
for (const req of range.requests) {
|
|
67504
|
+
const relOffset = req.offset - range.start;
|
|
67505
|
+
try {
|
|
67506
|
+
req._resolve({ buffer, relOffset, length: req.length });
|
|
67507
|
+
} catch (e) {
|
|
67508
|
+
req._reject(e);
|
|
67509
|
+
}
|
|
67510
|
+
}
|
|
67466
67511
|
}
|
|
67512
|
+
*/
|
|
67513
|
+
|
|
67514
|
+
const promises = finalRanges.map(async (range) => {
|
|
67515
|
+
const length = range.end - range.start;
|
|
67516
|
+
const buffer = await this.loadController.loadBinaryData([{ offset: range.start, length }]);
|
|
67517
|
+
for (const req of range.requests) {
|
|
67518
|
+
const relOffset = req.offset - range.start;
|
|
67519
|
+
try {
|
|
67520
|
+
req._resolve({ buffer, relOffset, length: req.length });
|
|
67521
|
+
} catch (e) {
|
|
67522
|
+
req._reject(e);
|
|
67523
|
+
}
|
|
67524
|
+
}
|
|
67525
|
+
});
|
|
67526
|
+
await Promise.all(promises);
|
|
67527
|
+
|
|
67528
|
+
this.pendingRequests = [];
|
|
67467
67529
|
}
|
|
67468
67530
|
|
|
67469
67531
|
getBufferView(byteOffset, byteLength, componentType) {
|
|
@@ -67476,12 +67538,10 @@ void main() {
|
|
|
67476
67538
|
|
|
67477
67539
|
createTypedArray(buffer, offset, length, componentType) {
|
|
67478
67540
|
try {
|
|
67479
|
-
// Validate parameters
|
|
67480
67541
|
if (!buffer || !(buffer instanceof ArrayBuffer)) {
|
|
67481
67542
|
throw new Error("Invalid buffer");
|
|
67482
67543
|
}
|
|
67483
67544
|
|
|
67484
|
-
// Calculate element size for given type
|
|
67485
67545
|
let elementSize;
|
|
67486
67546
|
switch (componentType) {
|
|
67487
67547
|
case 5120:
|
|
@@ -67500,18 +67560,15 @@ void main() {
|
|
|
67500
67560
|
throw new Error(`Unsupported component type: ${componentType}`);
|
|
67501
67561
|
}
|
|
67502
67562
|
|
|
67503
|
-
// Check if requested length is correct
|
|
67504
67563
|
const numElements = length / elementSize;
|
|
67505
67564
|
if (!Number.isInteger(numElements)) {
|
|
67506
67565
|
throw new Error(`Invalid length ${length} for component type ${componentType}`);
|
|
67507
67566
|
}
|
|
67508
67567
|
|
|
67509
|
-
// Check if buffer is large enough
|
|
67510
67568
|
if (length > buffer.byteLength) {
|
|
67511
67569
|
throw new Error(`Buffer too small: need ${length} bytes, but buffer is ${buffer.byteLength} bytes`);
|
|
67512
67570
|
}
|
|
67513
67571
|
|
|
67514
|
-
// Create appropriate typed array
|
|
67515
67572
|
const ArrayType = GL_COMPONENT_TYPES[componentType];
|
|
67516
67573
|
return new ArrayType(buffer, offset, numElements);
|
|
67517
67574
|
} catch (error) {
|
|
@@ -67608,7 +67665,6 @@ void main() {
|
|
|
67608
67665
|
const image = this.json.images[imageIndex];
|
|
67609
67666
|
|
|
67610
67667
|
if (image.uri) {
|
|
67611
|
-
// Handle base64 or URL
|
|
67612
67668
|
if (image.uri.startsWith("data:")) {
|
|
67613
67669
|
return await this.textureLoader.loadAsync(image.uri);
|
|
67614
67670
|
} else {
|
|
@@ -67616,23 +67672,17 @@ void main() {
|
|
|
67616
67672
|
return await this.textureLoader.loadAsync(fullUrl);
|
|
67617
67673
|
}
|
|
67618
67674
|
} else if (image.bufferView !== undefined) {
|
|
67619
|
-
// Handle embedded binary data
|
|
67620
67675
|
const bufferView = this.json.bufferViews[image.bufferView];
|
|
67621
|
-
const array = await this.getBufferView(
|
|
67622
|
-
bufferView.byteOffset || 0,
|
|
67623
|
-
bufferView.byteLength,
|
|
67624
|
-
5121 // UNSIGNED_BYTE
|
|
67625
|
-
);
|
|
67676
|
+
const array = await this.getBufferView(bufferView.byteOffset || 0, bufferView.byteLength, 5121);
|
|
67626
67677
|
const blob = new Blob([array], { type: image.mimeType });
|
|
67627
67678
|
const url = URL.createObjectURL(blob);
|
|
67628
67679
|
const texture = await this.textureLoader.loadAsync(url);
|
|
67629
67680
|
URL.revokeObjectURL(url);
|
|
67630
|
-
texture.flipY = false;
|
|
67681
|
+
texture.flipY = false;
|
|
67631
67682
|
return texture;
|
|
67632
67683
|
}
|
|
67633
67684
|
};
|
|
67634
67685
|
|
|
67635
|
-
// Load all textures
|
|
67636
67686
|
const texturePromises = [];
|
|
67637
67687
|
for (let i = 0; i < this.json.textures.length; i++) {
|
|
67638
67688
|
texturePromises.push(
|
|
@@ -67642,82 +67692,56 @@ void main() {
|
|
|
67642
67692
|
await Promise.all(texturePromises);
|
|
67643
67693
|
}
|
|
67644
67694
|
|
|
67645
|
-
loadMaterials() {
|
|
67695
|
+
async loadMaterials() {
|
|
67646
67696
|
if (!this.json.materials) return this.materials;
|
|
67647
67697
|
|
|
67648
67698
|
for (let i = 0; i < this.json.materials.length; i++) {
|
|
67649
67699
|
const materialDef = this.json.materials[i];
|
|
67650
|
-
const material = this.createMaterial(materialDef);
|
|
67700
|
+
const material = await this.createMaterial(materialDef);
|
|
67701
|
+
material.name = materialDef.name;
|
|
67651
67702
|
this.materials.set(i, material);
|
|
67652
67703
|
}
|
|
67653
67704
|
return this.materials;
|
|
67654
67705
|
}
|
|
67655
67706
|
|
|
67656
67707
|
createMaterial(materialDef) {
|
|
67657
|
-
const
|
|
67708
|
+
const params = {};
|
|
67658
67709
|
|
|
67659
|
-
// Base color
|
|
67660
67710
|
if (materialDef.pbrMetallicRoughness) {
|
|
67661
67711
|
const pbr = materialDef.pbrMetallicRoughness;
|
|
67662
|
-
|
|
67663
67712
|
if (pbr.baseColorFactor) {
|
|
67664
|
-
|
|
67665
|
-
|
|
67713
|
+
params.color = new Color().fromArray(pbr.baseColorFactor);
|
|
67714
|
+
params.opacity = pbr.baseColorFactor[3];
|
|
67715
|
+
if (params.opacity < 1.0) params.transparent = true;
|
|
67666
67716
|
}
|
|
67667
|
-
|
|
67668
67717
|
if (pbr.baseColorTexture) {
|
|
67669
|
-
|
|
67670
|
-
}
|
|
67671
|
-
|
|
67672
|
-
// Metallic and roughness
|
|
67673
|
-
if (pbr.metallicFactor !== undefined) {
|
|
67674
|
-
material.metalness = pbr.metallicFactor;
|
|
67675
|
-
}
|
|
67676
|
-
if (pbr.roughnessFactor !== undefined) {
|
|
67677
|
-
material.roughness = pbr.roughnessFactor;
|
|
67678
|
-
}
|
|
67679
|
-
if (pbr.metallicRoughnessTexture) {
|
|
67680
|
-
material.metalnessMap = this.textureCache.get(pbr.metallicRoughnessTexture.index);
|
|
67681
|
-
material.roughnessMap = material.metalnessMap;
|
|
67718
|
+
params.map = this.textureCache.get(pbr.baseColorTexture.index);
|
|
67682
67719
|
}
|
|
67683
67720
|
}
|
|
67684
67721
|
|
|
67685
|
-
|
|
67686
|
-
|
|
67687
|
-
|
|
67688
|
-
|
|
67689
|
-
|
|
67690
|
-
|
|
67691
|
-
}
|
|
67722
|
+
params.specular = 0x222222;
|
|
67723
|
+
params.shininess = 10;
|
|
67724
|
+
params.reflectivity = 0.05;
|
|
67725
|
+
params.polygonOffset = true;
|
|
67726
|
+
params.polygonOffsetFactor = 1;
|
|
67727
|
+
params.polygonOffsetUnits = 1;
|
|
67692
67728
|
|
|
67693
|
-
// Emissive
|
|
67694
67729
|
if (materialDef.emissiveFactor) {
|
|
67695
|
-
|
|
67696
|
-
}
|
|
67697
|
-
if (materialDef.emissiveTexture) {
|
|
67698
|
-
material.emissiveMap = this.textureCache.get(materialDef.emissiveTexture.index);
|
|
67730
|
+
params.emissive = new Color().fromArray(materialDef.emissiveFactor);
|
|
67699
67731
|
}
|
|
67700
67732
|
|
|
67701
|
-
|
|
67702
|
-
|
|
67703
|
-
material.aoMap = this.textureCache.get(materialDef.occlusionTexture.index);
|
|
67704
|
-
if (materialDef.occlusionTexture.strength !== undefined) {
|
|
67705
|
-
material.aoMapIntensity = materialDef.occlusionTexture.strength;
|
|
67706
|
-
}
|
|
67733
|
+
if (materialDef.normalTexture) {
|
|
67734
|
+
params.normalMap = this.textureCache.get(materialDef.normalTexture.index);
|
|
67707
67735
|
}
|
|
67708
67736
|
|
|
67709
|
-
// Alpha mode
|
|
67710
67737
|
if (materialDef.alphaMode === "BLEND") {
|
|
67711
|
-
|
|
67712
|
-
} else if (materialDef.alphaMode === "MASK") {
|
|
67713
|
-
material.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
|
|
67738
|
+
params.transparent = true;
|
|
67714
67739
|
}
|
|
67715
67740
|
|
|
67716
|
-
|
|
67717
|
-
|
|
67718
|
-
|
|
67719
|
-
material
|
|
67720
|
-
|
|
67741
|
+
if (materialDef.doubleSided) {
|
|
67742
|
+
params.side = DoubleSide;
|
|
67743
|
+
}
|
|
67744
|
+
const material = new MeshPhongMaterial(params);
|
|
67721
67745
|
return material;
|
|
67722
67746
|
}
|
|
67723
67747
|
|
|
@@ -67750,12 +67774,8 @@ void main() {
|
|
|
67750
67774
|
if (!meshDef || !meshDef.primitives) return 0;
|
|
67751
67775
|
|
|
67752
67776
|
let totalSize = 0;
|
|
67753
|
-
|
|
67754
|
-
// Estimate size for each primitive
|
|
67755
67777
|
for (const primitive of meshDef.primitives) {
|
|
67756
|
-
// Check for attributes
|
|
67757
67778
|
if (primitive.attributes) {
|
|
67758
|
-
// Calculate attributes size
|
|
67759
67779
|
for (const [, accessorIndex] of Object.entries(primitive.attributes)) {
|
|
67760
67780
|
if (accessorIndex === undefined) continue;
|
|
67761
67781
|
|
|
@@ -67768,7 +67788,6 @@ void main() {
|
|
|
67768
67788
|
}
|
|
67769
67789
|
}
|
|
67770
67790
|
|
|
67771
|
-
// Calculate indices size if present
|
|
67772
67791
|
if (primitive.indices !== undefined) {
|
|
67773
67792
|
const accessor = this.json.accessors[primitive.indices];
|
|
67774
67793
|
if (accessor) {
|
|
@@ -67841,7 +67860,9 @@ void main() {
|
|
|
67841
67860
|
this.mergedPoints = new Set();
|
|
67842
67861
|
|
|
67843
67862
|
this.isolatedObjects = [];
|
|
67844
|
-
|
|
67863
|
+
//!!window.WebGL2RenderingContext && this.renderer.getContext() instanceof WebGL2RenderingContext
|
|
67864
|
+
this.useVAO = false;
|
|
67865
|
+
this.visibleEdges = true;
|
|
67845
67866
|
|
|
67846
67867
|
this.handleToOptimizedObjects = new Map();
|
|
67847
67868
|
|
|
@@ -67850,6 +67871,10 @@ void main() {
|
|
|
67850
67871
|
this.oldOptimizeObjects = new Set();
|
|
67851
67872
|
}
|
|
67852
67873
|
|
|
67874
|
+
setVisibleEdges(visible) {
|
|
67875
|
+
this.visibleEdges = visible;
|
|
67876
|
+
}
|
|
67877
|
+
|
|
67853
67878
|
getAvailableMemory() {
|
|
67854
67879
|
let memoryLimit = 6 * 1024 * 1024 * 1024;
|
|
67855
67880
|
try {
|
|
@@ -67870,7 +67895,7 @@ void main() {
|
|
|
67870
67895
|
console.warn("Error detecting available memory:", error);
|
|
67871
67896
|
}
|
|
67872
67897
|
|
|
67873
|
-
return memoryLimit;
|
|
67898
|
+
return memoryLimit / 3;
|
|
67874
67899
|
}
|
|
67875
67900
|
|
|
67876
67901
|
getAbortController() {
|
|
@@ -67975,7 +68000,7 @@ void main() {
|
|
|
67975
68000
|
console.log(`Final memory usage: ${Math.round(currentMemoryUsage / (1024 * 1024))}MB`);
|
|
67976
68001
|
}
|
|
67977
68002
|
|
|
67978
|
-
async loadNode(nodeId) {
|
|
68003
|
+
async loadNode(nodeId, onLoadFinishCb) {
|
|
67979
68004
|
const node = this.nodes.get(nodeId);
|
|
67980
68005
|
if (!node || node.loaded || node.loading) return;
|
|
67981
68006
|
|
|
@@ -67983,38 +68008,138 @@ void main() {
|
|
|
67983
68008
|
const meshDef = node.structure.getJson().meshes[node.meshIndex];
|
|
67984
68009
|
|
|
67985
68010
|
try {
|
|
67986
|
-
|
|
67987
|
-
|
|
67988
|
-
|
|
67989
|
-
const
|
|
67990
|
-
|
|
67991
|
-
|
|
68011
|
+
const bufferRequests = [];
|
|
68012
|
+
const primitiveReqMap = new Map();
|
|
68013
|
+
for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
|
|
68014
|
+
const primitive = meshDef.primitives[primIdx];
|
|
68015
|
+
const reqs = [];
|
|
68016
|
+
|
|
68017
|
+
if (primitive.attributes.POSITION !== undefined) {
|
|
68018
|
+
const accessorIndex = primitive.attributes.POSITION;
|
|
68019
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
68020
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
68021
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
68022
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
68023
|
+
const count = accessor.count;
|
|
68024
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
68025
|
+
reqs.push({
|
|
68026
|
+
offset: byteOffset,
|
|
68027
|
+
length: byteLength,
|
|
68028
|
+
componentType: accessor.componentType,
|
|
68029
|
+
accessorIndex,
|
|
68030
|
+
type: "position",
|
|
68031
|
+
primIdx,
|
|
68032
|
+
});
|
|
68033
|
+
}
|
|
67992
68034
|
|
|
67993
68035
|
if (primitive.attributes.NORMAL !== undefined) {
|
|
67994
|
-
|
|
68036
|
+
const accessorIndex = primitive.attributes.NORMAL;
|
|
68037
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
68038
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
68039
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
68040
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
68041
|
+
const count = accessor.count;
|
|
68042
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
68043
|
+
reqs.push({
|
|
68044
|
+
offset: byteOffset,
|
|
68045
|
+
length: byteLength,
|
|
68046
|
+
componentType: accessor.componentType,
|
|
68047
|
+
accessorIndex,
|
|
68048
|
+
type: "normal",
|
|
68049
|
+
primIdx,
|
|
68050
|
+
});
|
|
67995
68051
|
}
|
|
67996
68052
|
|
|
67997
68053
|
if (primitive.attributes.TEXCOORD_0 !== undefined) {
|
|
67998
|
-
|
|
68054
|
+
const accessorIndex = primitive.attributes.TEXCOORD_0;
|
|
68055
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
68056
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
68057
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
68058
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
68059
|
+
const count = accessor.count;
|
|
68060
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
68061
|
+
reqs.push({
|
|
68062
|
+
offset: byteOffset,
|
|
68063
|
+
length: byteLength,
|
|
68064
|
+
componentType: accessor.componentType,
|
|
68065
|
+
accessorIndex,
|
|
68066
|
+
type: "uv",
|
|
68067
|
+
primIdx,
|
|
68068
|
+
});
|
|
67999
68069
|
}
|
|
68000
68070
|
|
|
68001
|
-
|
|
68002
|
-
|
|
68003
|
-
|
|
68004
|
-
|
|
68005
|
-
|
|
68006
|
-
|
|
68071
|
+
if (primitive.indices !== undefined) {
|
|
68072
|
+
const accessorIndex = primitive.indices;
|
|
68073
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
68074
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
68075
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
68076
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
68077
|
+
const count = accessor.count;
|
|
68078
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
68079
|
+
reqs.push({
|
|
68080
|
+
offset: byteOffset,
|
|
68081
|
+
length: byteLength,
|
|
68082
|
+
componentType: accessor.componentType,
|
|
68083
|
+
accessorIndex,
|
|
68084
|
+
type: "index",
|
|
68085
|
+
primIdx,
|
|
68086
|
+
});
|
|
68087
|
+
}
|
|
68088
|
+
primitiveReqMap.set(primIdx, reqs);
|
|
68089
|
+
bufferRequests.push(...reqs);
|
|
68090
|
+
}
|
|
68007
68091
|
|
|
68008
|
-
|
|
68009
|
-
|
|
68010
|
-
|
|
68092
|
+
if (bufferRequests.length === 0) {
|
|
68093
|
+
node.loaded = true;
|
|
68094
|
+
node.loading = false;
|
|
68095
|
+
return;
|
|
68096
|
+
}
|
|
68097
|
+
bufferRequests.sort((a, b) => a.offset - b.offset);
|
|
68098
|
+
const minOffset = bufferRequests[0].offset;
|
|
68099
|
+
const maxOffset = Math.max(...bufferRequests.map((r) => r.offset + r.length));
|
|
68100
|
+
const totalLength = maxOffset - minOffset;
|
|
68101
|
+
|
|
68102
|
+
const { buffer, relOffset: baseRelOffset } = await node.structure.scheduleRequest({
|
|
68103
|
+
offset: minOffset,
|
|
68104
|
+
length: totalLength,
|
|
68105
|
+
componentType: null,
|
|
68106
|
+
});
|
|
68011
68107
|
|
|
68012
|
-
|
|
68013
|
-
|
|
68014
|
-
|
|
68108
|
+
for (const req of bufferRequests) {
|
|
68109
|
+
const relOffset = req.offset - minOffset;
|
|
68110
|
+
req.data = node.structure.createTypedArray(buffer, baseRelOffset + relOffset, req.length, req.componentType);
|
|
68111
|
+
}
|
|
68112
|
+
|
|
68113
|
+
for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
|
|
68114
|
+
const primitive = meshDef.primitives[primIdx];
|
|
68115
|
+
const geometry = new BufferGeometry();
|
|
68116
|
+
const reqs = primitiveReqMap.get(primIdx);
|
|
68117
|
+
|
|
68118
|
+
if (primitive.attributes.POSITION !== undefined) {
|
|
68119
|
+
const req = reqs.find((r) => r.type === "position" && r.accessorIndex === primitive.attributes.POSITION);
|
|
68120
|
+
const accessor = node.structure.json.accessors[primitive.attributes.POSITION];
|
|
68121
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
68122
|
+
geometry.setAttribute("position", new BufferAttribute(req.data, components));
|
|
68123
|
+
}
|
|
68124
|
+
|
|
68125
|
+
if (primitive.attributes.NORMAL !== undefined) {
|
|
68126
|
+
const req = reqs.find((r) => r.type === "normal" && r.accessorIndex === primitive.attributes.NORMAL);
|
|
68127
|
+
const accessor = node.structure.json.accessors[primitive.attributes.NORMAL];
|
|
68128
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
68129
|
+
geometry.setAttribute("normal", new BufferAttribute(req.data, components));
|
|
68015
68130
|
}
|
|
68016
68131
|
|
|
68017
|
-
|
|
68132
|
+
if (primitive.attributes.TEXCOORD_0 !== undefined) {
|
|
68133
|
+
const req = reqs.find((r) => r.type === "uv" && r.accessorIndex === primitive.attributes.TEXCOORD_0);
|
|
68134
|
+
const accessor = node.structure.json.accessors[primitive.attributes.TEXCOORD_0];
|
|
68135
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
68136
|
+
geometry.setAttribute("uv", new BufferAttribute(req.data, components));
|
|
68137
|
+
}
|
|
68138
|
+
|
|
68139
|
+
if (primitive.indices !== undefined) {
|
|
68140
|
+
const req = reqs.find((r) => r.type === "index" && r.accessorIndex === primitive.indices);
|
|
68141
|
+
geometry.setIndex(new BufferAttribute(req.data, 1));
|
|
68142
|
+
}
|
|
68018
68143
|
|
|
68019
68144
|
let material;
|
|
68020
68145
|
if (primitive.material !== undefined) {
|
|
@@ -68029,8 +68154,7 @@ void main() {
|
|
|
68029
68154
|
Material.prototype.copy.call(pointsMaterial, material);
|
|
68030
68155
|
pointsMaterial.color.copy(material.color);
|
|
68031
68156
|
pointsMaterial.map = material.map;
|
|
68032
|
-
pointsMaterial.sizeAttenuation = false;
|
|
68033
|
-
|
|
68157
|
+
pointsMaterial.sizeAttenuation = false;
|
|
68034
68158
|
mesh = new Points(geometry, pointsMaterial);
|
|
68035
68159
|
} else if (
|
|
68036
68160
|
primitive.mode === GL_CONSTANTS.TRIANGLES ||
|
|
@@ -68039,7 +68163,6 @@ void main() {
|
|
|
68039
68163
|
primitive.mode === undefined
|
|
68040
68164
|
) {
|
|
68041
68165
|
mesh = new Mesh(geometry, material);
|
|
68042
|
-
|
|
68043
68166
|
if (primitive.mode === GL_CONSTANTS.TRIANGLE_STRIP) {
|
|
68044
68167
|
mesh.drawMode = TriangleStripDrawMode;
|
|
68045
68168
|
} else if (primitive.mode === GL_CONSTANTS.TRIANGLE_FAN) {
|
|
@@ -68052,39 +68175,30 @@ void main() {
|
|
|
68052
68175
|
} else if (primitive.mode === GL_CONSTANTS.LINE_LOOP) {
|
|
68053
68176
|
mesh = new LineLoop(geometry, material);
|
|
68054
68177
|
}
|
|
68055
|
-
|
|
68056
68178
|
if (node.extras) {
|
|
68057
68179
|
mesh.userData = { ...mesh.userData, ...node.extras };
|
|
68058
68180
|
}
|
|
68059
|
-
|
|
68060
68181
|
if (meshDef.extras) {
|
|
68061
68182
|
mesh.userData = { ...mesh.userData, ...meshDef.extras };
|
|
68062
68183
|
}
|
|
68063
|
-
|
|
68064
68184
|
if (primitive.extras) {
|
|
68065
68185
|
mesh.userData = { ...mesh.userData, ...primitive.extras };
|
|
68066
68186
|
}
|
|
68067
|
-
|
|
68068
68187
|
if (node.handle) {
|
|
68069
68188
|
mesh.userData.handle = node.handle;
|
|
68070
68189
|
} else {
|
|
68071
68190
|
mesh.userData.handle = `${node.structure.id}_${mesh.userData.handle}`;
|
|
68072
68191
|
}
|
|
68073
|
-
|
|
68074
68192
|
if (mesh.material.name === "edges") {
|
|
68075
68193
|
mesh.userData.isEdge = true;
|
|
68076
68194
|
} else {
|
|
68077
68195
|
mesh.userData.isEdge = false;
|
|
68078
68196
|
}
|
|
68079
|
-
|
|
68080
68197
|
this.registerObjectWithHandle(mesh, mesh.userData.handle);
|
|
68081
|
-
|
|
68082
68198
|
mesh.position.copy(node.position);
|
|
68083
|
-
|
|
68084
68199
|
if (!geometry.attributes.normal) {
|
|
68085
68200
|
geometry.computeVertexNormals();
|
|
68086
68201
|
}
|
|
68087
|
-
|
|
68088
68202
|
if (material.aoMap && geometry.attributes.uv) {
|
|
68089
68203
|
geometry.setAttribute("uv2", geometry.attributes.uv);
|
|
68090
68204
|
}
|
|
@@ -68094,17 +68208,17 @@ void main() {
|
|
|
68094
68208
|
this.scene.add(mesh);
|
|
68095
68209
|
}
|
|
68096
68210
|
node.object = mesh;
|
|
68097
|
-
|
|
68098
68211
|
this.totalLoadedObjects++;
|
|
68099
68212
|
mesh.visible = this.totalLoadedObjects < this.graphicsObjectLimit;
|
|
68100
68213
|
}
|
|
68101
|
-
|
|
68102
68214
|
node.loaded = true;
|
|
68103
68215
|
node.loading = false;
|
|
68104
|
-
|
|
68105
68216
|
const geometrySize = this.estimateGeometrySize(node.object);
|
|
68106
68217
|
this.geometryCache.set(node.object.uuid, geometrySize);
|
|
68107
68218
|
this.currentMemoryUsage += geometrySize;
|
|
68219
|
+
if (onLoadFinishCb) {
|
|
68220
|
+
onLoadFinishCb();
|
|
68221
|
+
}
|
|
68108
68222
|
} catch (error) {
|
|
68109
68223
|
if (error.name !== "AbortError") {
|
|
68110
68224
|
console.error(`Error loading node ${nodeId}:`, error);
|
|
@@ -68229,7 +68343,7 @@ void main() {
|
|
|
68229
68343
|
return volumeB - volumeA;
|
|
68230
68344
|
});
|
|
68231
68345
|
|
|
68232
|
-
if (!ignoreEdges) {
|
|
68346
|
+
if (!ignoreEdges && this.visibleEdges) {
|
|
68233
68347
|
this.nodesToLoad.push(...this.edgeNodes);
|
|
68234
68348
|
}
|
|
68235
68349
|
|
|
@@ -68356,33 +68470,13 @@ void main() {
|
|
|
68356
68470
|
async processNodes() {
|
|
68357
68471
|
const nodesToLoad = this.nodesToLoad;
|
|
68358
68472
|
let loadedCount = 0;
|
|
68473
|
+
let lastLoadedCount = 0;
|
|
68359
68474
|
const totalNodes = nodesToLoad.length;
|
|
68360
68475
|
|
|
68361
|
-
|
|
68362
|
-
|
|
68363
|
-
|
|
68364
|
-
|
|
68365
|
-
|
|
68366
|
-
for (const nodeId of batch) {
|
|
68367
|
-
if (this.abortController.signal.aborted) {
|
|
68368
|
-
throw new DOMException("Loading aborted", "AbortError");
|
|
68369
|
-
}
|
|
68370
|
-
|
|
68371
|
-
const estimatedSize = await this.estimateNodeSize(nodeId);
|
|
68372
|
-
|
|
68373
|
-
if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
|
|
68374
|
-
console.log(`Memory limit reached after loading ${loadedCount} nodes`);
|
|
68375
|
-
this.dispatchEvent("geometryerror", { message: "Memory limit reached" });
|
|
68376
|
-
this.dispatchEvent("update");
|
|
68377
|
-
return loadedCount;
|
|
68378
|
-
}
|
|
68379
|
-
|
|
68380
|
-
batchPromises.push(this.loadNode(nodeId));
|
|
68381
|
-
}
|
|
68382
|
-
|
|
68383
|
-
await Promise.all(batchPromises);
|
|
68384
|
-
loadedCount += batch.length;
|
|
68385
|
-
|
|
68476
|
+
const loadProgress = async () => {
|
|
68477
|
+
loadedCount++;
|
|
68478
|
+
if (loadedCount - lastLoadedCount > 1000) {
|
|
68479
|
+
lastLoadedCount = loadedCount;
|
|
68386
68480
|
this.updateMemoryIndicator();
|
|
68387
68481
|
this.dispatchEvent("geometryprogress", {
|
|
68388
68482
|
percentage: Math.round((loadedCount / totalNodes) * 100),
|
|
@@ -68400,6 +68494,34 @@ void main() {
|
|
|
68400
68494
|
setTimeout(resolve, 0);
|
|
68401
68495
|
});
|
|
68402
68496
|
}
|
|
68497
|
+
};
|
|
68498
|
+
|
|
68499
|
+
try {
|
|
68500
|
+
const loadOperations = [];
|
|
68501
|
+
for (const nodeId of nodesToLoad) {
|
|
68502
|
+
if (this.abortController.signal.aborted) {
|
|
68503
|
+
throw new DOMException("Loading aborted", "AbortError");
|
|
68504
|
+
}
|
|
68505
|
+
|
|
68506
|
+
const estimatedSize = await this.estimateNodeSize(nodeId);
|
|
68507
|
+
|
|
68508
|
+
if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
|
|
68509
|
+
console.log(`Memory limit reached after loading ${loadedCount} nodes`);
|
|
68510
|
+
this.dispatchEvent("geometryerror", {
|
|
68511
|
+
message: "Memory limit reached",
|
|
68512
|
+
});
|
|
68513
|
+
this.dispatchEvent("update");
|
|
68514
|
+
return loadedCount;
|
|
68515
|
+
}
|
|
68516
|
+
|
|
68517
|
+
loadOperations.push(this.loadNode(nodeId, loadProgress));
|
|
68518
|
+
}
|
|
68519
|
+
|
|
68520
|
+
for (const structure of this.structures) {
|
|
68521
|
+
loadOperations.push(structure.flushBufferRequests());
|
|
68522
|
+
}
|
|
68523
|
+
|
|
68524
|
+
await Promise.all(loadOperations);
|
|
68403
68525
|
|
|
68404
68526
|
this.dispatchEvent("geometryend", {
|
|
68405
68527
|
totalLoaded: loadedCount,
|
|
@@ -69380,6 +69502,25 @@ void main() {
|
|
|
69380
69502
|
}
|
|
69381
69503
|
});
|
|
69382
69504
|
}
|
|
69505
|
+
|
|
69506
|
+
// Возвращает bounding box для конкретной структуры
|
|
69507
|
+
getStructureGeometryExtent(structureId) {
|
|
69508
|
+
const extent = new Box3();
|
|
69509
|
+
for (const [nodeId, node] of this.nodes.entries()) {
|
|
69510
|
+
if (!node.geometryExtents) continue;
|
|
69511
|
+
if (!nodeId.startsWith(structureId + "_")) continue;
|
|
69512
|
+
if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
|
|
69513
|
+
const transformedBox = node.geometryExtents.clone();
|
|
69514
|
+
if (node.group && node.group.matrix) {
|
|
69515
|
+
transformedBox.applyMatrix4(node.group.matrix);
|
|
69516
|
+
if (node.group.parent && node.group.parent.matrix) {
|
|
69517
|
+
transformedBox.applyMatrix4(node.group.parent.matrix);
|
|
69518
|
+
}
|
|
69519
|
+
}
|
|
69520
|
+
extent.union(transformedBox);
|
|
69521
|
+
}
|
|
69522
|
+
return extent;
|
|
69523
|
+
}
|
|
69383
69524
|
}
|
|
69384
69525
|
|
|
69385
69526
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -69408,7 +69549,6 @@ void main() {
|
|
|
69408
69549
|
constructor(viewer) {
|
|
69409
69550
|
this.requestId = 0;
|
|
69410
69551
|
this.viewer = viewer;
|
|
69411
|
-
this.scene = new Group$1();
|
|
69412
69552
|
}
|
|
69413
69553
|
dispose() {
|
|
69414
69554
|
if (this.gltfLoader)
|
|
@@ -69422,27 +69562,25 @@ void main() {
|
|
|
69422
69562
|
/.gltf$/i.test(file.database));
|
|
69423
69563
|
}
|
|
69424
69564
|
async load(model, format, params) {
|
|
69425
|
-
|
|
69565
|
+
const scene = new Group$1();
|
|
69566
|
+
this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
|
|
69426
69567
|
this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
|
|
69427
69568
|
this.gltfLoader.addEventListener("databasechunk", (data) => {
|
|
69428
|
-
const modelImpl = new DynamicModelImpl(
|
|
69569
|
+
const modelImpl = new DynamicModelImpl(scene);
|
|
69429
69570
|
modelImpl.loader = this;
|
|
69430
69571
|
modelImpl.gltfLoader = this.gltfLoader;
|
|
69431
69572
|
modelImpl.viewer = this.viewer;
|
|
69432
|
-
this.viewer.scene.add(
|
|
69573
|
+
this.viewer.scene.add(scene);
|
|
69433
69574
|
this.viewer.models.push(modelImpl);
|
|
69434
69575
|
this.viewer.syncOptions();
|
|
69435
69576
|
this.viewer.syncOverlay();
|
|
69436
69577
|
this.viewer.update();
|
|
69437
|
-
this.viewer.emitEvent({ type: "databasechunk", data, file: model.file, model });
|
|
69578
|
+
this.viewer.emitEvent({ type: "databasechunk", data: scene, file: model.file, model });
|
|
69438
69579
|
});
|
|
69439
69580
|
this.gltfLoader.addEventListener("geometryprogress", (data) => {
|
|
69440
69581
|
const progress = data.loaded / data.total;
|
|
69441
69582
|
this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model.file, model });
|
|
69442
69583
|
});
|
|
69443
|
-
this.gltfLoader.addEventListener("geometrymemory", (data) => {
|
|
69444
|
-
this.viewer.emit({ type: "geometryprogress", data });
|
|
69445
|
-
});
|
|
69446
69584
|
this.gltfLoader.addEventListener("geometryerror", (data) => {
|
|
69447
69585
|
this.viewer.emitEvent({ type: "geometryerror", data, file: model.file, model });
|
|
69448
69586
|
});
|
|
@@ -69476,9 +69614,8 @@ void main() {
|
|
|
69476
69614
|
return this;
|
|
69477
69615
|
}
|
|
69478
69616
|
cancel() {
|
|
69479
|
-
if (this.gltfLoader)
|
|
69617
|
+
if (this.gltfLoader)
|
|
69480
69618
|
this.gltfLoader.abortLoading();
|
|
69481
|
-
}
|
|
69482
69619
|
}
|
|
69483
69620
|
}
|
|
69484
69621
|
|
|
@@ -69516,7 +69653,7 @@ void main() {
|
|
|
69516
69653
|
*
|
|
69517
69654
|
* The loader should do:
|
|
69518
69655
|
*
|
|
69519
|
-
* - Load
|
|
69656
|
+
* - Load raw data from file and convert it to the `Three.js` scene.
|
|
69520
69657
|
* - Add scene to the viewer `scene`.
|
|
69521
69658
|
* - Create `ModelImpl` for the scene and to the viewer `models` list.
|
|
69522
69659
|
* - Synchronize viewer options and overlay.
|