@inweb/viewer-three 26.12.5 → 26.12.7
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/extensions/loaders/GLTFFileLoader.js +1 -1
- package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -1
- package/dist/extensions/loaders/GLTFFileLoader.min.js +1 -1
- package/dist/extensions/loaders/GLTFFileLoader.module.js +1 -1
- package/dist/extensions/loaders/GLTFFileLoader.module.js.map +1 -1
- package/dist/extensions/loaders/IFCXLoader.js +2 -2
- package/dist/extensions/loaders/IFCXLoader.js.map +1 -1
- package/dist/extensions/loaders/IFCXLoader.min.js +1 -1
- package/dist/extensions/loaders/IFCXLoader.module.js +2 -2
- package/dist/extensions/loaders/IFCXLoader.module.js.map +1 -1
- package/dist/viewer-three.js +467 -164
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +465 -162
- package/dist/viewer-three.module.js.map +1 -1
- package/extensions/loaders/GLTFFileLoader.ts +1 -1
- package/extensions/loaders/IFCX/IFCXCloudLoader.ts +1 -1
- package/extensions/loaders/IFCX/IFCXFileLoader.ts +1 -1
- package/lib/Viewer/components/ExtentsComponent.d.ts +1 -1
- package/lib/Viewer/components/ResetComponent.d.ts +1 -1
- package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +3 -3
- package/lib/Viewer/measurement/Snapper.d.ts +1 -0
- package/lib/Viewer/measurement/UnitConverter.d.ts +20 -13
- package/lib/Viewer/models/IModelImpl.d.ts +2 -6
- package/lib/Viewer/models/ModelImpl.d.ts +4 -6
- package/package.json +5 -5
- package/src/Viewer/Viewer.ts +15 -11
- package/src/Viewer/commands/GetSelected2.ts +2 -2
- package/src/Viewer/commands/ResetView.ts +0 -5
- package/src/Viewer/commands/ZoomTo.ts +3 -3
- package/src/Viewer/components/CameraComponent.ts +4 -4
- package/src/Viewer/components/ExtentsComponent.ts +3 -3
- package/src/Viewer/components/HighlighterComponent.ts +11 -17
- package/src/Viewer/components/ResetComponent.ts +5 -2
- package/src/Viewer/components/SelectionComponent.ts +14 -13
- package/src/Viewer/draggers/MeasureLineDragger.ts +1 -0
- package/src/Viewer/draggers/OrbitDragger.ts +2 -0
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +285 -10
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +94 -18
- package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +1 -1
- package/src/Viewer/measurement/Snapper.ts +6 -3
- package/src/Viewer/measurement/UnitConverter.ts +19 -12
- package/src/Viewer/measurement/UnitFormatter.ts +2 -2
- package/src/Viewer/models/IModelImpl.ts +2 -10
- package/src/Viewer/models/ModelImpl.ts +111 -61
|
@@ -805,6 +805,7 @@ class OrbitDragger {
|
|
|
805
805
|
this.changed = false;
|
|
806
806
|
this.viewer = viewer;
|
|
807
807
|
this.viewer.addEventListener("databasechunk", this.updateControls);
|
|
808
|
+
this.viewer.addEventListener("clear", this.updateControls);
|
|
808
809
|
this.viewer.on("viewposition", this.updateControls);
|
|
809
810
|
this.viewer.addEventListener("zoom", this.updateControls);
|
|
810
811
|
this.viewer.addEventListener("drawviewpoint", this.updateControls);
|
|
@@ -816,6 +817,7 @@ class OrbitDragger {
|
|
|
816
817
|
initialize() { }
|
|
817
818
|
dispose() {
|
|
818
819
|
this.viewer.removeEventListener("databasechunk", this.updateControls);
|
|
820
|
+
this.viewer.removeEventListener("clear", this.updateControls);
|
|
819
821
|
this.viewer.off("viewposition", this.updateControls);
|
|
820
822
|
this.viewer.removeEventListener("zoom", this.updateControls);
|
|
821
823
|
this.viewer.removeEventListener("drawviewpoint", this.updateControls);
|
|
@@ -913,20 +915,25 @@ class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
|
|
|
913
915
|
}
|
|
914
916
|
}
|
|
915
917
|
|
|
918
|
+
const DisplayUnits = {
|
|
919
|
+
Meters: { name: "Meters", symbol: "m", scale: 1.0 },
|
|
920
|
+
Centimeters: { name: "Centimeters", symbol: "cm", scale: 0.01 },
|
|
921
|
+
Millimeters: { name: "Millimeters", symbol: "mm", scale: 0.001 },
|
|
922
|
+
Feet: { name: "Feet", symbol: "ft", scale: 0.3048 },
|
|
923
|
+
Inches: { name: "Inches", symbol: "in", scale: 0.0254 },
|
|
924
|
+
Yards: { name: "Yards", symbol: "yd", scale: 0.9144 },
|
|
925
|
+
Kilometers: { name: "Kilometers", symbol: "km", scale: 1000.0 },
|
|
926
|
+
Miles: { name: "Miles", symbol: "mi", scale: 1609.344 },
|
|
927
|
+
Micrometers: { name: "Micrometers", symbol: "µm", scale: 0.000001 },
|
|
928
|
+
Mils: { name: "Mils", symbol: "mil", scale: 0.0000254 },
|
|
929
|
+
MicroInches: { name: "Micro-inches", symbol: "µin", scale: 0.0000000254 },
|
|
930
|
+
Default: { name: "File units", symbol: "", scale: 1.0 },
|
|
931
|
+
};
|
|
916
932
|
const ModelUnits = {
|
|
917
|
-
|
|
918
|
-
Centimeters: { name: "Centimeters", type: "cm", scale: 0.01 },
|
|
919
|
-
Millimeters: { name: "Millimeters", type: "mm", scale: 0.001 },
|
|
920
|
-
Feet: { name: "Feet", type: "ft", scale: 0.3048 },
|
|
921
|
-
Inches: { name: "Inches", type: "in", scale: 0.0254 },
|
|
922
|
-
Yards: { name: "Yards", type: "yd", scale: 0.9144 },
|
|
923
|
-
Kilometers: { name: "Kilometers", type: "km", scale: 1000.0 },
|
|
924
|
-
Miles: { name: "Miles", type: "mi", scale: 1609.344 },
|
|
925
|
-
Micrometers: { name: "Micrometers", type: "µm", scale: 0.000001 },
|
|
926
|
-
Mils: { name: "Mils", type: "mil", scale: 0.0000254 },
|
|
927
|
-
MicroInches: { name: "Micro-inches", type: "µin", scale: 0.0000000254 },
|
|
928
|
-
Default: { name: "File units", type: "unit", scale: 1.0 },
|
|
933
|
+
Default: { name: "", symbol: "", scale: 1.0 },
|
|
929
934
|
};
|
|
935
|
+
Object.keys(DisplayUnits).forEach((key) => (ModelUnits[key] = DisplayUnits[key]));
|
|
936
|
+
Object.keys(DisplayUnits).forEach((key) => (ModelUnits[DisplayUnits[key].symbol] = DisplayUnits[key]));
|
|
930
937
|
function convertUnits(fromUnits, toUnits, distance) {
|
|
931
938
|
const fromFactor = 1 / (ModelUnits[fromUnits] || ModelUnits.Default).scale;
|
|
932
939
|
const toFactor = (ModelUnits[toUnits] || ModelUnits.Default).scale || 1;
|
|
@@ -934,7 +941,7 @@ function convertUnits(fromUnits, toUnits, distance) {
|
|
|
934
941
|
}
|
|
935
942
|
|
|
936
943
|
function getDisplayUnit(units) {
|
|
937
|
-
return (ModelUnits[units] || ModelUnits.Default).
|
|
944
|
+
return (ModelUnits[units] || ModelUnits.Default).symbol;
|
|
938
945
|
}
|
|
939
946
|
function calculatePrecision(value) {
|
|
940
947
|
const distance = Math.abs(value);
|
|
@@ -971,7 +978,7 @@ function formatDistance(distance, units, precision = 2) {
|
|
|
971
978
|
else if (digits > 10)
|
|
972
979
|
digits = 10;
|
|
973
980
|
if (ModelUnits[units]) {
|
|
974
|
-
return formatNumber(distance, digits, precision) + " " + ModelUnits[units].
|
|
981
|
+
return formatNumber(distance, digits, precision) + " " + ModelUnits[units].symbol;
|
|
975
982
|
}
|
|
976
983
|
else if (units) {
|
|
977
984
|
return formatNumber(distance, digits, precision) + " " + units;
|
|
@@ -994,6 +1001,7 @@ class Snapper {
|
|
|
994
1001
|
this.camera = camera;
|
|
995
1002
|
this.renderer = renderer;
|
|
996
1003
|
this.canvas = canvas;
|
|
1004
|
+
this.threshold = 0.0001;
|
|
997
1005
|
this.raycaster = new Raycaster();
|
|
998
1006
|
this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
|
|
999
1007
|
this.edgesCache = new WeakMap();
|
|
@@ -1014,10 +1022,10 @@ class Snapper {
|
|
|
1014
1022
|
this.raycaster.setFromCamera(coords, this.camera);
|
|
1015
1023
|
this.raycaster.params = {
|
|
1016
1024
|
Mesh: {},
|
|
1017
|
-
Line: { threshold:
|
|
1018
|
-
Line2: { threshold:
|
|
1025
|
+
Line: { threshold: this.threshold },
|
|
1026
|
+
Line2: { threshold: this.threshold },
|
|
1019
1027
|
LOD: {},
|
|
1020
|
-
Points: { threshold:
|
|
1028
|
+
Points: { threshold: this.threshold },
|
|
1021
1029
|
Sprite: {},
|
|
1022
1030
|
};
|
|
1023
1031
|
let intersects = this.raycaster.intersectObjects(objects, false);
|
|
@@ -1186,6 +1194,7 @@ class MeasureLineDragger extends OrbitDragger {
|
|
|
1186
1194
|
this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
|
|
1187
1195
|
this.overlay.addLine(this.line);
|
|
1188
1196
|
this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
|
|
1197
|
+
this.snapper.threshold = viewer.extents.getSize(new Vector3()).length() / 10000;
|
|
1189
1198
|
this.objects = [];
|
|
1190
1199
|
this.updateObjects();
|
|
1191
1200
|
this.updateUnits();
|
|
@@ -2189,7 +2198,7 @@ function zoomTo(viewer, box) {
|
|
|
2189
2198
|
const boxCenter = box.getCenter(new Vector3());
|
|
2190
2199
|
const boxSize = box.getBoundingSphere(new Sphere()).radius;
|
|
2191
2200
|
const rendererSize = viewer.renderer.getSize(new Vector2());
|
|
2192
|
-
const
|
|
2201
|
+
const aspectRatio = rendererSize.x / rendererSize.y;
|
|
2193
2202
|
const camera = viewer.camera;
|
|
2194
2203
|
if (camera.isPerspectiveCamera) {
|
|
2195
2204
|
const offset = new Vector3(0, 0, 1)
|
|
@@ -2201,8 +2210,8 @@ function zoomTo(viewer, box) {
|
|
|
2201
2210
|
if (camera.isOrthographicCamera) {
|
|
2202
2211
|
camera.top = boxSize;
|
|
2203
2212
|
camera.bottom = -boxSize;
|
|
2204
|
-
camera.left = camera.bottom *
|
|
2205
|
-
camera.right = camera.top *
|
|
2213
|
+
camera.left = camera.bottom * aspectRatio;
|
|
2214
|
+
camera.right = camera.top * aspectRatio;
|
|
2206
2215
|
camera.zoom = 1;
|
|
2207
2216
|
camera.updateProjectionMatrix();
|
|
2208
2217
|
const offset = new Vector3(0, 0, 1)
|
|
@@ -2263,9 +2272,9 @@ function getSelected(viewer) {
|
|
|
2263
2272
|
function getSelected2(viewer) {
|
|
2264
2273
|
const handles2 = [];
|
|
2265
2274
|
viewer.models.forEach((model) => {
|
|
2266
|
-
handles2.push(
|
|
2275
|
+
handles2.push(model.getHandlesByObjects(viewer.selected));
|
|
2267
2276
|
});
|
|
2268
|
-
return handles2;
|
|
2277
|
+
return handles2.flat();
|
|
2269
2278
|
}
|
|
2270
2279
|
|
|
2271
2280
|
function hideSelected(viewer) {
|
|
@@ -2289,7 +2298,6 @@ function regenerateAll(viewer) {
|
|
|
2289
2298
|
}
|
|
2290
2299
|
|
|
2291
2300
|
function resetView(viewer) {
|
|
2292
|
-
const reset = viewer.getComponent("ResetComponent");
|
|
2293
2301
|
viewer.executeCommand("setActiveDragger");
|
|
2294
2302
|
viewer.executeCommand("clearSlices");
|
|
2295
2303
|
viewer.executeCommand("clearOverlay");
|
|
@@ -2298,7 +2306,6 @@ function resetView(viewer) {
|
|
|
2298
2306
|
viewer.executeCommand("showAll");
|
|
2299
2307
|
viewer.executeCommand("explode", 0);
|
|
2300
2308
|
viewer.executeCommand("zoomToExtents", true);
|
|
2301
|
-
reset.resetCameraPosition();
|
|
2302
2309
|
viewer.emit({ type: "resetview" });
|
|
2303
2310
|
}
|
|
2304
2311
|
|
|
@@ -2491,15 +2498,15 @@ class CameraComponent {
|
|
|
2491
2498
|
switchCamera(camera) {
|
|
2492
2499
|
const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2 || 1;
|
|
2493
2500
|
const rendererSize = this.viewer.renderer.getSize(new Vector2());
|
|
2494
|
-
const
|
|
2501
|
+
const aspectRatio = rendererSize.x / rendererSize.y;
|
|
2495
2502
|
if (camera.isPerspectiveCamera) {
|
|
2496
|
-
camera.aspect =
|
|
2503
|
+
camera.aspect = aspectRatio;
|
|
2497
2504
|
camera.near = extentsSize / 1000;
|
|
2498
2505
|
camera.far = extentsSize * 1000;
|
|
2499
2506
|
}
|
|
2500
2507
|
if (camera.isOrthographicCamera) {
|
|
2501
|
-
camera.left = camera.bottom *
|
|
2502
|
-
camera.right = camera.top *
|
|
2508
|
+
camera.left = camera.bottom * aspectRatio;
|
|
2509
|
+
camera.right = camera.top * aspectRatio;
|
|
2503
2510
|
camera.near = 0;
|
|
2504
2511
|
camera.far = extentsSize * 1000;
|
|
2505
2512
|
}
|
|
@@ -2547,10 +2554,12 @@ class CameraComponent {
|
|
|
2547
2554
|
|
|
2548
2555
|
class ExtentsComponent {
|
|
2549
2556
|
constructor(viewer) {
|
|
2550
|
-
this.syncExtents = () => {
|
|
2557
|
+
this.syncExtents = (event) => {
|
|
2551
2558
|
const extents = new Box3();
|
|
2552
2559
|
this.viewer.models.forEach((model) => model.getExtents(extents));
|
|
2553
2560
|
this.viewer.extents.copy(extents);
|
|
2561
|
+
if (event.type !== "databasechunk" && event.target !== "clear")
|
|
2562
|
+
return;
|
|
2554
2563
|
if (this.viewer.models.length > 1)
|
|
2555
2564
|
return;
|
|
2556
2565
|
this.viewer.extents.getCenter(this.viewer.target);
|
|
@@ -2917,12 +2926,12 @@ class HighlighterComponent {
|
|
|
2917
2926
|
const { edgesVisibility } = this.viewer.options;
|
|
2918
2927
|
if (!Array.isArray(objects))
|
|
2919
2928
|
objects = [objects];
|
|
2920
|
-
if (
|
|
2929
|
+
if (objects.length === 0)
|
|
2921
2930
|
return;
|
|
2922
2931
|
objects
|
|
2923
2932
|
.filter((object) => !object.userData.isEdge)
|
|
2924
2933
|
.forEach((object) => {
|
|
2925
|
-
if (object.isHighlighted)
|
|
2934
|
+
if (object.userData.isHighlighted)
|
|
2926
2935
|
return;
|
|
2927
2936
|
if (object.isLine || object.isLineSegments) {
|
|
2928
2937
|
const positions = object.geometry.attributes.position.array;
|
|
@@ -2931,43 +2940,39 @@ class HighlighterComponent {
|
|
|
2931
2940
|
? HighlighterUtils.fromIndexedLine(positions, indices)
|
|
2932
2941
|
: HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
|
|
2933
2942
|
const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
|
|
2934
|
-
wireframe.position.copy(object.position);
|
|
2935
|
-
wireframe.rotation.copy(object.rotation);
|
|
2936
|
-
wireframe.scale.copy(object.scale);
|
|
2937
2943
|
wireframe.visible = edgesVisibility;
|
|
2938
|
-
|
|
2944
|
+
wireframe.userData.isHighlightWireframe = true;
|
|
2945
|
+
object.add(wireframe);
|
|
2939
2946
|
object.userData.highlightWireframe = wireframe;
|
|
2940
2947
|
object.userData.originalMaterial = object.material;
|
|
2941
2948
|
object.material = this.lineMaterial;
|
|
2942
|
-
object.isHighlighted = true;
|
|
2949
|
+
object.userData.isHighlighted = true;
|
|
2943
2950
|
}
|
|
2944
2951
|
else if (object.isMesh) {
|
|
2945
2952
|
const edgesGeometry = new EdgesGeometry(object.geometry, 89);
|
|
2946
2953
|
const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
|
|
2947
2954
|
const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
|
|
2948
|
-
wireframe.position.copy(object.position);
|
|
2949
|
-
wireframe.rotation.copy(object.rotation);
|
|
2950
|
-
wireframe.scale.copy(object.scale);
|
|
2951
2955
|
wireframe.visible = edgesVisibility;
|
|
2952
|
-
|
|
2956
|
+
wireframe.userData.isHighlightWireframe = true;
|
|
2957
|
+
object.add(wireframe);
|
|
2953
2958
|
object.userData.highlightWireframe = wireframe;
|
|
2954
2959
|
object.userData.originalMaterial = object.material;
|
|
2955
2960
|
object.material = this.facesMaterial;
|
|
2956
|
-
object.isHighlighted = true;
|
|
2961
|
+
object.userData.isHighlighted = true;
|
|
2957
2962
|
}
|
|
2958
2963
|
});
|
|
2959
2964
|
}
|
|
2960
2965
|
unhighlight(objects) {
|
|
2961
2966
|
if (!Array.isArray(objects))
|
|
2962
2967
|
objects = [objects];
|
|
2963
|
-
if (
|
|
2968
|
+
if (objects.length === 0)
|
|
2964
2969
|
return;
|
|
2965
2970
|
objects.forEach((object) => {
|
|
2966
|
-
if (!object.isHighlighted)
|
|
2971
|
+
if (!object.userData.isHighlighted)
|
|
2967
2972
|
return;
|
|
2968
|
-
object.isHighlighted = false;
|
|
2969
2973
|
object.material = object.userData.originalMaterial;
|
|
2970
2974
|
object.userData.highlightWireframe.removeFromParent();
|
|
2975
|
+
delete object.userData.isHighlighted;
|
|
2971
2976
|
delete object.userData.originalMaterial;
|
|
2972
2977
|
delete object.userData.highlightWireframe;
|
|
2973
2978
|
});
|
|
@@ -3015,6 +3020,7 @@ class SelectionComponent {
|
|
|
3015
3020
|
if (upPosition.distanceTo(this.downPosition) !== 0)
|
|
3016
3021
|
return;
|
|
3017
3022
|
const snapper = new Snapper(this.viewer.camera, this.viewer.renderer, this.viewer.canvas);
|
|
3023
|
+
snapper.threshold = this.viewer.extents.getSize(new Vector3()).length() / 10000;
|
|
3018
3024
|
let intersections = [];
|
|
3019
3025
|
this.viewer.models.forEach((model) => {
|
|
3020
3026
|
const objects = model.getVisibleObjects();
|
|
@@ -3069,12 +3075,12 @@ class SelectionComponent {
|
|
|
3069
3075
|
}
|
|
3070
3076
|
if (!Array.isArray(objects))
|
|
3071
3077
|
objects = [objects];
|
|
3072
|
-
if (
|
|
3078
|
+
if (objects.length === 0)
|
|
3073
3079
|
return;
|
|
3074
|
-
model.
|
|
3080
|
+
model.highlightObjects(objects);
|
|
3075
3081
|
this.highlighter.highlight(objects);
|
|
3076
3082
|
objects.forEach((object) => this.viewer.selected.push(object));
|
|
3077
|
-
objects.forEach((object) => (object.isSelected = true));
|
|
3083
|
+
objects.forEach((object) => (object.userData.isSelected = true));
|
|
3078
3084
|
}
|
|
3079
3085
|
deselect(objects, model) {
|
|
3080
3086
|
if (!model) {
|
|
@@ -3083,29 +3089,29 @@ class SelectionComponent {
|
|
|
3083
3089
|
}
|
|
3084
3090
|
if (!Array.isArray(objects))
|
|
3085
3091
|
objects = [objects];
|
|
3086
|
-
if (
|
|
3092
|
+
if (objects.length === 0)
|
|
3087
3093
|
return;
|
|
3094
|
+
model.unhighlightObjects(objects);
|
|
3088
3095
|
this.highlighter.unhighlight(objects);
|
|
3089
|
-
model.hideOriginalObjects(objects);
|
|
3090
3096
|
this.viewer.selected = this.viewer.selected.filter((x) => !objects.includes(x));
|
|
3091
|
-
objects.forEach((object) => (object.isSelected = false));
|
|
3097
|
+
objects.forEach((object) => (object.userData.isSelected = false));
|
|
3092
3098
|
}
|
|
3093
3099
|
toggleSelection(objects, model) {
|
|
3094
3100
|
if (!Array.isArray(objects))
|
|
3095
3101
|
objects = [objects];
|
|
3096
|
-
if (
|
|
3102
|
+
if (objects.length === 0)
|
|
3097
3103
|
return;
|
|
3098
|
-
if (objects[0].isSelected)
|
|
3104
|
+
if (objects[0].userData.isSelected)
|
|
3099
3105
|
this.deselect(objects, model);
|
|
3100
3106
|
else
|
|
3101
3107
|
this.select(objects, model);
|
|
3102
3108
|
}
|
|
3103
3109
|
clearSelection() {
|
|
3104
|
-
if (
|
|
3110
|
+
if (this.viewer.selected.length === 0)
|
|
3105
3111
|
return;
|
|
3112
|
+
this.viewer.models.forEach((model) => model.unhighlightObjects(this.viewer.selected));
|
|
3106
3113
|
this.highlighter.unhighlight(this.viewer.selected);
|
|
3107
|
-
this.viewer.
|
|
3108
|
-
this.viewer.selected.forEach((object) => (object.isSelected = false));
|
|
3114
|
+
this.viewer.selected.forEach((object) => (object.userData.isSelected = false));
|
|
3109
3115
|
this.viewer.selected.length = 0;
|
|
3110
3116
|
}
|
|
3111
3117
|
}
|
|
@@ -3233,19 +3239,22 @@ class ResetComponent {
|
|
|
3233
3239
|
direction: this.viewer.camera.getWorldDirection(new Vector3()),
|
|
3234
3240
|
};
|
|
3235
3241
|
};
|
|
3242
|
+
this.resetCameraPosition = () => {
|
|
3243
|
+
if (this.savedCameraPosition) {
|
|
3244
|
+
this.viewer.camera.position.copy(this.savedCameraPosition.position);
|
|
3245
|
+
this.viewer.camera.up.copy(this.savedCameraPosition.up);
|
|
3246
|
+
this.viewer.camera.lookAt(this.savedCameraPosition.position.clone().add(this.savedCameraPosition.direction));
|
|
3247
|
+
this.viewer.camera.updateProjectionMatrix();
|
|
3248
|
+
}
|
|
3249
|
+
};
|
|
3236
3250
|
this.viewer = viewer;
|
|
3237
3251
|
this.viewer.addEventListener("databasechunk", this.onDatabaseChunk);
|
|
3252
|
+
this.viewer.on("resetview", this.resetCameraPosition);
|
|
3238
3253
|
}
|
|
3239
3254
|
dispose() {
|
|
3255
|
+
this.viewer.off("resetview", this.resetCameraPosition);
|
|
3240
3256
|
this.viewer.removeEventListener("databasechunk", this.onDatabaseChunk);
|
|
3241
3257
|
}
|
|
3242
|
-
resetCameraPosition() {
|
|
3243
|
-
if (this.savedCameraPosition) {
|
|
3244
|
-
this.viewer.camera.position.copy(this.savedCameraPosition.position);
|
|
3245
|
-
this.viewer.camera.up.copy(this.savedCameraPosition.up);
|
|
3246
|
-
this.viewer.camera.lookAt(this.savedCameraPosition.position.clone().add(this.savedCameraPosition.direction));
|
|
3247
|
-
}
|
|
3248
|
-
}
|
|
3249
3258
|
}
|
|
3250
3259
|
|
|
3251
3260
|
const components = componentsRegistry("threejs");
|
|
@@ -3264,6 +3273,20 @@ components.registerComponent("ResetComponent", (viewer) => new ResetComponent(vi
|
|
|
3264
3273
|
class ModelImpl {
|
|
3265
3274
|
constructor(scene) {
|
|
3266
3275
|
this.scene = scene;
|
|
3276
|
+
this.handleToObjects = new Map();
|
|
3277
|
+
this.originalObjects = new Set();
|
|
3278
|
+
this.scene.traverse((object) => {
|
|
3279
|
+
this.originalObjects.add(object);
|
|
3280
|
+
const handle = object.userData.handle;
|
|
3281
|
+
if (!handle)
|
|
3282
|
+
return;
|
|
3283
|
+
let objects = this.handleToObjects.get(handle);
|
|
3284
|
+
if (!objects) {
|
|
3285
|
+
objects = new Set();
|
|
3286
|
+
this.handleToObjects.set(handle, objects);
|
|
3287
|
+
}
|
|
3288
|
+
objects.add(object);
|
|
3289
|
+
});
|
|
3267
3290
|
}
|
|
3268
3291
|
dispose() {
|
|
3269
3292
|
function disposeMaterial(material) {
|
|
@@ -3279,6 +3302,8 @@ class ModelImpl {
|
|
|
3279
3302
|
if (object.material)
|
|
3280
3303
|
disposeMaterials(object.material);
|
|
3281
3304
|
}
|
|
3305
|
+
this.handleToObjects = undefined;
|
|
3306
|
+
this.originalObjects = undefined;
|
|
3282
3307
|
this.scene.traverse(disposeObject);
|
|
3283
3308
|
this.scene.clear();
|
|
3284
3309
|
}
|
|
@@ -3421,67 +3446,56 @@ class ModelImpl {
|
|
|
3421
3446
|
return info;
|
|
3422
3447
|
}
|
|
3423
3448
|
getExtents(target) {
|
|
3424
|
-
this.scene.traverseVisible((object) =>
|
|
3449
|
+
this.scene.traverseVisible((object) => target.expandByObject(object));
|
|
3425
3450
|
return target;
|
|
3426
3451
|
}
|
|
3427
3452
|
getObjects() {
|
|
3428
|
-
|
|
3429
|
-
this.scene.traverse((object) => objects.push(object));
|
|
3430
|
-
return objects;
|
|
3453
|
+
return Array.from(this.originalObjects);
|
|
3431
3454
|
}
|
|
3432
3455
|
getVisibleObjects() {
|
|
3433
3456
|
const objects = [];
|
|
3434
3457
|
this.scene.traverseVisible((object) => objects.push(object));
|
|
3435
|
-
return objects;
|
|
3436
|
-
}
|
|
3437
|
-
hasObject(object) {
|
|
3438
|
-
while (object) {
|
|
3439
|
-
if (object === this.scene)
|
|
3440
|
-
return true;
|
|
3441
|
-
object = object.parent;
|
|
3442
|
-
}
|
|
3443
|
-
return false;
|
|
3444
|
-
}
|
|
3445
|
-
hasHandle(handle) {
|
|
3446
|
-
return !handle.includes(":") || handle.split(":", 1)[0] === this.id + "";
|
|
3458
|
+
return objects.filter((object) => object.userData.handle);
|
|
3447
3459
|
}
|
|
3448
|
-
|
|
3449
|
-
if (!Array.isArray(objects))
|
|
3450
|
-
objects = [objects];
|
|
3451
|
-
return objects.filter((object) => this.hasObject(object));
|
|
3452
|
-
}
|
|
3453
|
-
getOwnHandles(handles) {
|
|
3460
|
+
getObjectsByHandles(handles) {
|
|
3454
3461
|
if (!Array.isArray(handles))
|
|
3455
3462
|
handles = [handles];
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
+
const ownHandles = [];
|
|
3464
|
+
handles.forEach((handle) => {
|
|
3465
|
+
const index = handle.indexOf(":");
|
|
3466
|
+
if (index !== -1) {
|
|
3467
|
+
if (handle.slice(0, index) !== this.id)
|
|
3468
|
+
return;
|
|
3469
|
+
handle = handle.slice(index + 1);
|
|
3470
|
+
}
|
|
3471
|
+
ownHandles.push(handle);
|
|
3472
|
+
});
|
|
3473
|
+
const handlesSet = new Set(ownHandles);
|
|
3463
3474
|
const objects = [];
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
if (handle && handleSet.has(handle))
|
|
3467
|
-
objects.push(object);
|
|
3475
|
+
handlesSet.forEach((handle) => {
|
|
3476
|
+
objects.push(Array.from(this.handleToObjects.get(handle) || []));
|
|
3468
3477
|
});
|
|
3469
|
-
return objects;
|
|
3478
|
+
return objects.flat();
|
|
3470
3479
|
}
|
|
3471
3480
|
getHandlesByObjects(objects) {
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
return [];
|
|
3481
|
+
if (!Array.isArray(objects))
|
|
3482
|
+
objects = [objects];
|
|
3475
3483
|
const handleSet = new Set();
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3484
|
+
objects
|
|
3485
|
+
.filter((object) => this.originalObjects.has(object))
|
|
3486
|
+
.forEach((object) => {
|
|
3487
|
+
handleSet.add(`${this.id}:${object.userData.handle}`);
|
|
3480
3488
|
});
|
|
3481
3489
|
return Array.from(handleSet);
|
|
3482
3490
|
}
|
|
3483
3491
|
hideObjects(objects) {
|
|
3484
|
-
|
|
3492
|
+
if (!Array.isArray(objects))
|
|
3493
|
+
objects = [objects];
|
|
3494
|
+
objects
|
|
3495
|
+
.filter((object) => this.originalObjects.has(object))
|
|
3496
|
+
.forEach((object) => {
|
|
3497
|
+
object.visible = false;
|
|
3498
|
+
});
|
|
3485
3499
|
return this;
|
|
3486
3500
|
}
|
|
3487
3501
|
hideAllObjects() {
|
|
@@ -3491,12 +3505,20 @@ class ModelImpl {
|
|
|
3491
3505
|
if (!Array.isArray(objects))
|
|
3492
3506
|
objects = [objects];
|
|
3493
3507
|
const visibleSet = new Set(objects);
|
|
3494
|
-
|
|
3508
|
+
objects
|
|
3509
|
+
.filter((object) => this.originalObjects.has(object))
|
|
3510
|
+
.forEach((object) => {
|
|
3511
|
+
object.traverseAncestors((parent) => visibleSet.add(parent));
|
|
3512
|
+
});
|
|
3495
3513
|
this.scene.traverse((object) => (object.visible = visibleSet.has(object)));
|
|
3496
3514
|
return this;
|
|
3497
3515
|
}
|
|
3498
3516
|
showObjects(objects) {
|
|
3499
|
-
|
|
3517
|
+
if (!Array.isArray(objects))
|
|
3518
|
+
objects = [objects];
|
|
3519
|
+
objects
|
|
3520
|
+
.filter((object) => this.originalObjects.has(object))
|
|
3521
|
+
.forEach((object) => {
|
|
3500
3522
|
object.visible = true;
|
|
3501
3523
|
object.traverseAncestors((parent) => (parent.visible = true));
|
|
3502
3524
|
});
|
|
@@ -3506,36 +3528,55 @@ class ModelImpl {
|
|
|
3506
3528
|
this.scene.traverse((object) => (object.visible = true));
|
|
3507
3529
|
return this;
|
|
3508
3530
|
}
|
|
3509
|
-
|
|
3531
|
+
highlightObjects(objects) {
|
|
3510
3532
|
return this;
|
|
3511
3533
|
}
|
|
3512
|
-
|
|
3534
|
+
unhighlightObjects(objects) {
|
|
3513
3535
|
return this;
|
|
3514
3536
|
}
|
|
3515
3537
|
explode(scale = 0, coeff = 4) {
|
|
3538
|
+
const centers = new Map();
|
|
3539
|
+
const getObjectCenter = (object, target) => {
|
|
3540
|
+
const extents = new Box3().setFromObject(object);
|
|
3541
|
+
const handle = object.userData.handle;
|
|
3542
|
+
if (!handle)
|
|
3543
|
+
return extents.getCenter(target);
|
|
3544
|
+
const center = centers.get(handle);
|
|
3545
|
+
if (center)
|
|
3546
|
+
return target.copy(center);
|
|
3547
|
+
const objects = this.getObjectsByHandles(handle);
|
|
3548
|
+
objects.forEach((x) => extents.expandByObject(x));
|
|
3549
|
+
extents.getCenter(target);
|
|
3550
|
+
centers.set(handle, target.clone());
|
|
3551
|
+
return target;
|
|
3552
|
+
};
|
|
3516
3553
|
function calcExplodeDepth(object, depth) {
|
|
3517
|
-
let
|
|
3554
|
+
let result = depth;
|
|
3518
3555
|
object.children.forEach((x) => {
|
|
3519
3556
|
const objectDepth = calcExplodeDepth(x, depth + 1);
|
|
3520
|
-
if (
|
|
3521
|
-
|
|
3557
|
+
if (result < objectDepth)
|
|
3558
|
+
result = objectDepth;
|
|
3522
3559
|
});
|
|
3523
3560
|
object.userData.originalPosition = object.position.clone();
|
|
3524
|
-
object.userData.originalCenter =
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
if (!
|
|
3530
|
-
|
|
3531
|
-
const maxDepth =
|
|
3532
|
-
const scaledExplodeDepth =
|
|
3561
|
+
object.userData.originalCenter = getObjectCenter(object, new Vector3());
|
|
3562
|
+
return result;
|
|
3563
|
+
}
|
|
3564
|
+
const explodeScale = scale / 100;
|
|
3565
|
+
const explodeRoot = this.scene;
|
|
3566
|
+
if (!explodeRoot.userData.explodeDepth)
|
|
3567
|
+
explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
|
|
3568
|
+
const maxDepth = explodeRoot.userData.explodeDepth;
|
|
3569
|
+
const scaledExplodeDepth = explodeScale * maxDepth + 1;
|
|
3533
3570
|
const explodeDepth = 0 | scaledExplodeDepth;
|
|
3534
3571
|
const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
|
|
3535
3572
|
function explodeObject(object, depth) {
|
|
3573
|
+
if (object.isCamera)
|
|
3574
|
+
return;
|
|
3575
|
+
if (object.userData.isHighlightWireframe)
|
|
3576
|
+
return;
|
|
3536
3577
|
object.position.copy(object.userData.originalPosition);
|
|
3537
|
-
if (depth > 0 && depth <= explodeDepth
|
|
3538
|
-
let objectScale =
|
|
3578
|
+
if (depth > 0 && depth <= explodeDepth) {
|
|
3579
|
+
let objectScale = explodeScale * coeff;
|
|
3539
3580
|
if (depth === explodeDepth)
|
|
3540
3581
|
objectScale *= currentSegmentFraction;
|
|
3541
3582
|
const parentCenter = object.parent.userData.originalCenter;
|
|
@@ -3545,7 +3586,7 @@ class ModelImpl {
|
|
|
3545
3586
|
}
|
|
3546
3587
|
object.children.forEach((x) => explodeObject(x, depth + 1));
|
|
3547
3588
|
}
|
|
3548
|
-
explodeObject(
|
|
3589
|
+
explodeObject(explodeRoot, 0);
|
|
3549
3590
|
this.scene.updateMatrixWorld();
|
|
3550
3591
|
return this;
|
|
3551
3592
|
}
|
|
@@ -3583,29 +3624,24 @@ class DynamicModelImpl extends ModelImpl {
|
|
|
3583
3624
|
getVisibleObjects() {
|
|
3584
3625
|
return this.gltfLoader.getOriginalObjectForSelect();
|
|
3585
3626
|
}
|
|
3586
|
-
hasObject(object) {
|
|
3587
|
-
return this.gltfLoader.originalObjects.has(object);
|
|
3588
|
-
}
|
|
3589
3627
|
getObjectsByHandles(handles) {
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
const handlesSet = new Set(ownHandles);
|
|
3628
|
+
if (!Array.isArray(handles))
|
|
3629
|
+
handles = [handles];
|
|
3630
|
+
const handlesSet = new Set(handles);
|
|
3594
3631
|
const objects = [];
|
|
3595
3632
|
handlesSet.forEach((handle) => {
|
|
3596
|
-
objects.push(
|
|
3633
|
+
objects.push(this.gltfLoader.getObjectsByHandle(handle));
|
|
3597
3634
|
});
|
|
3598
|
-
return objects;
|
|
3635
|
+
return objects.flat();
|
|
3599
3636
|
}
|
|
3600
3637
|
getHandlesByObjects(objects) {
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
return [];
|
|
3638
|
+
if (!Array.isArray(objects))
|
|
3639
|
+
objects = [objects];
|
|
3604
3640
|
const handleSet = new Set();
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3641
|
+
objects
|
|
3642
|
+
.filter((object) => this.gltfLoader.originalObjects.has(object))
|
|
3643
|
+
.forEach((object) => {
|
|
3644
|
+
handleSet.add(object.userData.handle);
|
|
3609
3645
|
});
|
|
3610
3646
|
return Array.from(handleSet);
|
|
3611
3647
|
}
|
|
@@ -3628,14 +3664,78 @@ class DynamicModelImpl extends ModelImpl {
|
|
|
3628
3664
|
this.gltfLoader.showAllHiddenObjects();
|
|
3629
3665
|
return this;
|
|
3630
3666
|
}
|
|
3631
|
-
|
|
3667
|
+
highlightObjects(objects) {
|
|
3632
3668
|
this.gltfLoader.showOriginalObjects(objects);
|
|
3633
3669
|
return this;
|
|
3634
3670
|
}
|
|
3635
|
-
|
|
3671
|
+
unhighlightObjects(objects) {
|
|
3636
3672
|
this.gltfLoader.hideOriginalObjects(objects);
|
|
3637
3673
|
return this;
|
|
3638
3674
|
}
|
|
3675
|
+
explode(scale = 0, coeff = 4) {
|
|
3676
|
+
const centers = new Map();
|
|
3677
|
+
const calcObjectCenter = (object, target) => {
|
|
3678
|
+
const extents = new Box3().setFromObject(object);
|
|
3679
|
+
const handle = object.userData.handle;
|
|
3680
|
+
if (!handle)
|
|
3681
|
+
return extents.getCenter(target);
|
|
3682
|
+
const center = centers.get(handle);
|
|
3683
|
+
if (center)
|
|
3684
|
+
return target.copy(center);
|
|
3685
|
+
const objects = this.getObjectsByHandles(handle);
|
|
3686
|
+
objects.forEach((x) => extents.expandByObject(x));
|
|
3687
|
+
extents.getCenter(target);
|
|
3688
|
+
centers.set(handle, target.clone());
|
|
3689
|
+
return target;
|
|
3690
|
+
};
|
|
3691
|
+
function calcExplodeDepth(object, depth) {
|
|
3692
|
+
let result = depth;
|
|
3693
|
+
object.children
|
|
3694
|
+
.filter((x) => !x.userData.isOptimized)
|
|
3695
|
+
.forEach((x) => {
|
|
3696
|
+
const objectDepth = calcExplodeDepth(x, depth + 1);
|
|
3697
|
+
if (result < objectDepth)
|
|
3698
|
+
result = objectDepth;
|
|
3699
|
+
});
|
|
3700
|
+
object.userData.originalPosition = object.position.clone();
|
|
3701
|
+
object.userData.originalCenter = calcObjectCenter(object, new Vector3());
|
|
3702
|
+
return result;
|
|
3703
|
+
}
|
|
3704
|
+
const explodeScale = scale / 100;
|
|
3705
|
+
const explodeRoot = this.scene.children[0];
|
|
3706
|
+
if (!explodeRoot.userData.explodeDepth)
|
|
3707
|
+
explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
|
|
3708
|
+
const maxDepth = explodeRoot.userData.explodeDepth;
|
|
3709
|
+
const scaledExplodeDepth = explodeScale * maxDepth + 1;
|
|
3710
|
+
const explodeDepth = 0 | scaledExplodeDepth;
|
|
3711
|
+
const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
|
|
3712
|
+
const transformMap = new Map();
|
|
3713
|
+
function explodeObject(object, depth) {
|
|
3714
|
+
if (object.isCamera)
|
|
3715
|
+
return;
|
|
3716
|
+
if (object.userData.isHighlightWireframe)
|
|
3717
|
+
return;
|
|
3718
|
+
object.position.copy(object.userData.originalPosition);
|
|
3719
|
+
if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
|
|
3720
|
+
let objectScale = explodeScale * coeff;
|
|
3721
|
+
if (depth === explodeDepth)
|
|
3722
|
+
objectScale *= currentSegmentFraction;
|
|
3723
|
+
const parentCenter = object.parent.userData.originalCenter;
|
|
3724
|
+
const objectCenter = object.userData.originalCenter;
|
|
3725
|
+
const objectOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
|
|
3726
|
+
object.position.add(objectOffset);
|
|
3727
|
+
const matrix = new Matrix4().makeTranslation(objectOffset.x, objectOffset.y, objectOffset.z);
|
|
3728
|
+
transformMap.set(object, matrix);
|
|
3729
|
+
}
|
|
3730
|
+
object.children
|
|
3731
|
+
.filter((x) => !x.userData.isOptimized)
|
|
3732
|
+
.forEach((x) => explodeObject(x, depth + 1));
|
|
3733
|
+
}
|
|
3734
|
+
explodeObject(explodeRoot, 0);
|
|
3735
|
+
this.scene.updateMatrixWorld();
|
|
3736
|
+
this.gltfLoader.applyObjectTransforms(transformMap);
|
|
3737
|
+
return this;
|
|
3738
|
+
}
|
|
3639
3739
|
}
|
|
3640
3740
|
|
|
3641
3741
|
const GL_COMPONENT_TYPES = {
|
|
@@ -3684,7 +3784,7 @@ class GltfStructure {
|
|
|
3684
3784
|
this.textureCache = new Map();
|
|
3685
3785
|
this.materialCache = new Map();
|
|
3686
3786
|
this.uri = "";
|
|
3687
|
-
this._nextObjectId =
|
|
3787
|
+
this._nextObjectId = 1;
|
|
3688
3788
|
this.loadingAborted = false;
|
|
3689
3789
|
this.criticalError = null;
|
|
3690
3790
|
}
|
|
@@ -4203,6 +4303,8 @@ class DynamicGltfLoader {
|
|
|
4203
4303
|
this.hiddenHandles = new Set();
|
|
4204
4304
|
this.newOptimizedObjects = new Set();
|
|
4205
4305
|
this.oldOptimizeObjects = new Set();
|
|
4306
|
+
this.objectTransforms = new Map();
|
|
4307
|
+
this.transformedGeometries = new Map();
|
|
4206
4308
|
this.activeChunkLoads = 0;
|
|
4207
4309
|
this.chunkQueue = [];
|
|
4208
4310
|
this.objectIdToIndex = new Map();
|
|
@@ -4964,14 +5066,32 @@ class DynamicGltfLoader {
|
|
|
4964
5066
|
if (!node.geometryExtents) continue;
|
|
4965
5067
|
if (node.object && this.hiddenHandles.has(node.object.userData.handle)) continue;
|
|
4966
5068
|
const transformedBox = node.geometryExtents.clone();
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
5069
|
+
const structureRoot = node.structure ? this.structureRoots.get(node.structure.id) : null;
|
|
5070
|
+
if (node.group) {
|
|
5071
|
+
const matrices = [];
|
|
5072
|
+
let currentGroup = node.group;
|
|
5073
|
+
while (currentGroup && currentGroup !== structureRoot) {
|
|
5074
|
+
if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
|
|
5075
|
+
matrices.unshift(currentGroup.matrix);
|
|
5076
|
+
}
|
|
5077
|
+
currentGroup = currentGroup.parent;
|
|
5078
|
+
}
|
|
5079
|
+
for (const matrix of matrices) {
|
|
5080
|
+
transformedBox.applyMatrix4(matrix);
|
|
4971
5081
|
}
|
|
4972
5082
|
}
|
|
5083
|
+
if (structureRoot && structureRoot.matrix) {
|
|
5084
|
+
transformedBox.applyMatrix4(structureRoot.matrix);
|
|
5085
|
+
}
|
|
5086
|
+
const transform = this.objectTransforms.get(node.object);
|
|
5087
|
+
if (transform) {
|
|
5088
|
+
transformedBox.applyMatrix4(transform);
|
|
5089
|
+
}
|
|
4973
5090
|
totalExtent.union(transformedBox);
|
|
4974
5091
|
}
|
|
5092
|
+
if (this.scene && this.scene.matrix && !totalExtent.isEmpty()) {
|
|
5093
|
+
totalExtent.applyMatrix4(this.scene.matrix);
|
|
5094
|
+
}
|
|
4975
5095
|
return totalExtent;
|
|
4976
5096
|
}
|
|
4977
5097
|
loadCamera(structure, cameraIndex, nodeDef) {
|
|
@@ -5047,7 +5167,6 @@ class DynamicGltfLoader {
|
|
|
5047
5167
|
for (let i = 0; i < this.maxObjectId; i++) {
|
|
5048
5168
|
this.objectVisibility[i] = 1.0;
|
|
5049
5169
|
}
|
|
5050
|
-
console.log(`Initialized object visibility array: ${this.maxObjectId} objects`);
|
|
5051
5170
|
}
|
|
5052
5171
|
}
|
|
5053
5172
|
createVisibilityMaterial(material) {
|
|
@@ -5184,6 +5303,8 @@ class DynamicGltfLoader {
|
|
|
5184
5303
|
this.newOptimizedObjects.clear();
|
|
5185
5304
|
this.oldOptimizeObjects.clear();
|
|
5186
5305
|
this.isolatedObjects = [];
|
|
5306
|
+
this.objectTransforms.clear();
|
|
5307
|
+
this.transformedGeometries.clear();
|
|
5187
5308
|
this.totalLoadedObjects = 0;
|
|
5188
5309
|
this.lastUpdateTime = 0;
|
|
5189
5310
|
this.currentMemoryUsage = 0;
|
|
@@ -5881,6 +6002,171 @@ class DynamicGltfLoader {
|
|
|
5881
6002
|
mergedObject.geometry.attributes.visibility.needsUpdate = true;
|
|
5882
6003
|
}
|
|
5883
6004
|
}
|
|
6005
|
+
applyObjectTransforms(objectTransformMap) {
|
|
6006
|
+
if (this.mergedObjectMap.size === 0) {
|
|
6007
|
+
console.warn("No merged objects to transform");
|
|
6008
|
+
return;
|
|
6009
|
+
}
|
|
6010
|
+
this.objectTransforms = new Map(objectTransformMap);
|
|
6011
|
+
for (const mesh of this.mergedMesh) {
|
|
6012
|
+
this._applyTransformToMergedObject(mesh);
|
|
6013
|
+
}
|
|
6014
|
+
for (const line of this.mergedLines) {
|
|
6015
|
+
this._applyTransformToMergedObject(line);
|
|
6016
|
+
}
|
|
6017
|
+
for (const lineSegment of this.mergedLineSegments) {
|
|
6018
|
+
this._applyTransformToMergedObject(lineSegment);
|
|
6019
|
+
}
|
|
6020
|
+
for (const point of this.mergedPoints) {
|
|
6021
|
+
this._applyTransformToMergedObject(point);
|
|
6022
|
+
}
|
|
6023
|
+
}
|
|
6024
|
+
createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
|
|
6025
|
+
const transformMap = new Map();
|
|
6026
|
+
if (!explodeCenter) {
|
|
6027
|
+
explodeCenter = new Vector3();
|
|
6028
|
+
const extent = this.getTotalGeometryExtent();
|
|
6029
|
+
if (!extent.isEmpty()) {
|
|
6030
|
+
extent.getCenter(explodeCenter);
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
6033
|
+
const objectsArray = objects
|
|
6034
|
+
? Array.isArray(objects)
|
|
6035
|
+
? objects
|
|
6036
|
+
: Array.from(objects)
|
|
6037
|
+
: Array.from(this.originalObjects);
|
|
6038
|
+
for (const obj of objectsArray) {
|
|
6039
|
+
if (!obj.geometry || !obj.geometry.attributes.position) continue;
|
|
6040
|
+
const boundingBox = new Box3().setFromBufferAttribute(obj.geometry.attributes.position);
|
|
6041
|
+
if (obj.matrixWorld) {
|
|
6042
|
+
boundingBox.applyMatrix4(obj.matrixWorld);
|
|
6043
|
+
}
|
|
6044
|
+
if (boundingBox.isEmpty()) continue;
|
|
6045
|
+
const objectCenter = new Vector3();
|
|
6046
|
+
boundingBox.getCenter(objectCenter);
|
|
6047
|
+
const direction = objectCenter.clone().sub(explodeCenter);
|
|
6048
|
+
const distance = direction.length();
|
|
6049
|
+
if (distance > 0) {
|
|
6050
|
+
direction.normalize();
|
|
6051
|
+
const offset = direction.multiplyScalar(distance * (explodeFactor - 1.0));
|
|
6052
|
+
const matrix = new Matrix4().makeTranslation(offset.x, offset.y, offset.z);
|
|
6053
|
+
transformMap.set(obj, matrix);
|
|
6054
|
+
}
|
|
6055
|
+
}
|
|
6056
|
+
return transformMap;
|
|
6057
|
+
}
|
|
6058
|
+
clearTransforms() {
|
|
6059
|
+
this.objectTransforms.clear();
|
|
6060
|
+
for (const mesh of this.mergedMesh) {
|
|
6061
|
+
this._restoreOriginalGeometry(mesh);
|
|
6062
|
+
}
|
|
6063
|
+
for (const line of this.mergedLines) {
|
|
6064
|
+
this._restoreOriginalGeometry(line);
|
|
6065
|
+
}
|
|
6066
|
+
for (const lineSegment of this.mergedLineSegments) {
|
|
6067
|
+
this._restoreOriginalGeometry(lineSegment);
|
|
6068
|
+
}
|
|
6069
|
+
for (const point of this.mergedPoints) {
|
|
6070
|
+
this._restoreOriginalGeometry(point);
|
|
6071
|
+
}
|
|
6072
|
+
}
|
|
6073
|
+
clearHandleTransforms() {
|
|
6074
|
+
this.clearTransforms();
|
|
6075
|
+
}
|
|
6076
|
+
_applyTransformToMergedObject(mergedObject) {
|
|
6077
|
+
const objectData = this.mergedObjectMap.get(mergedObject.uuid);
|
|
6078
|
+
if (!objectData || !objectData.objectMapping) return;
|
|
6079
|
+
const geometry = mergedObject.geometry;
|
|
6080
|
+
if (!geometry || !geometry.attributes.position) return;
|
|
6081
|
+
const positionAttr = geometry.attributes.position;
|
|
6082
|
+
const positions = positionAttr.array;
|
|
6083
|
+
if (!this.transformedGeometries.has(mergedObject.uuid)) {
|
|
6084
|
+
this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
|
|
6085
|
+
}
|
|
6086
|
+
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
6087
|
+
const tempVector = new Vector3();
|
|
6088
|
+
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
6089
|
+
const transform = this.objectTransforms.get(originalMesh);
|
|
6090
|
+
if (!transform) {
|
|
6091
|
+
const startIdx = mappingData.startVertexIndex * 3;
|
|
6092
|
+
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
6093
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
6094
|
+
positions[i] = originalPositions[i];
|
|
6095
|
+
}
|
|
6096
|
+
continue;
|
|
6097
|
+
}
|
|
6098
|
+
const startVertex = mappingData.startVertexIndex;
|
|
6099
|
+
const vertexCount = mappingData.vertexCount;
|
|
6100
|
+
for (let i = 0; i < vertexCount; i++) {
|
|
6101
|
+
const idx = (startVertex + i) * 3;
|
|
6102
|
+
tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
|
|
6103
|
+
tempVector.applyMatrix4(transform);
|
|
6104
|
+
positions[idx] = tempVector.x;
|
|
6105
|
+
positions[idx + 1] = tempVector.y;
|
|
6106
|
+
positions[idx + 2] = tempVector.z;
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
if (geometry.attributes.normal) {
|
|
6110
|
+
this._updateNormalsForTransform(geometry, objectData, originalPositions);
|
|
6111
|
+
}
|
|
6112
|
+
positionAttr.needsUpdate = true;
|
|
6113
|
+
geometry.computeBoundingSphere();
|
|
6114
|
+
geometry.computeBoundingBox();
|
|
6115
|
+
}
|
|
6116
|
+
_updateNormalsForTransform(geometry, objectData, originalPositions) {
|
|
6117
|
+
const normalAttr = geometry.attributes.normal;
|
|
6118
|
+
if (!normalAttr) return;
|
|
6119
|
+
const normals = normalAttr.array;
|
|
6120
|
+
const tempVector = new Vector3();
|
|
6121
|
+
const normalMatrix = new Matrix4();
|
|
6122
|
+
const normalsKey = `${geometry.uuid}_normals`;
|
|
6123
|
+
if (!this.transformedGeometries.has(normalsKey)) {
|
|
6124
|
+
this.transformedGeometries.set(normalsKey, new Float32Array(normals));
|
|
6125
|
+
}
|
|
6126
|
+
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
6127
|
+
for (const [originalMesh, mappingData] of objectData.objectMapping) {
|
|
6128
|
+
const transform = this.objectTransforms.get(originalMesh);
|
|
6129
|
+
if (!transform) {
|
|
6130
|
+
const startIdx = mappingData.startVertexIndex * 3;
|
|
6131
|
+
const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
|
|
6132
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
6133
|
+
normals[i] = originalNormals[i];
|
|
6134
|
+
}
|
|
6135
|
+
continue;
|
|
6136
|
+
}
|
|
6137
|
+
normalMatrix.copy(transform).invert().transpose();
|
|
6138
|
+
const startVertex = mappingData.startVertexIndex;
|
|
6139
|
+
const vertexCount = mappingData.vertexCount;
|
|
6140
|
+
for (let i = 0; i < vertexCount; i++) {
|
|
6141
|
+
const idx = (startVertex + i) * 3;
|
|
6142
|
+
tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
|
|
6143
|
+
tempVector.applyMatrix4(normalMatrix).normalize();
|
|
6144
|
+
normals[idx] = tempVector.x;
|
|
6145
|
+
normals[idx + 1] = tempVector.y;
|
|
6146
|
+
normals[idx + 2] = tempVector.z;
|
|
6147
|
+
}
|
|
6148
|
+
}
|
|
6149
|
+
normalAttr.needsUpdate = true;
|
|
6150
|
+
}
|
|
6151
|
+
_restoreOriginalGeometry(mergedObject) {
|
|
6152
|
+
const geometry = mergedObject.geometry;
|
|
6153
|
+
if (!geometry || !geometry.attributes.position) return;
|
|
6154
|
+
const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
|
|
6155
|
+
if (originalPositions) {
|
|
6156
|
+
const positions = geometry.attributes.position.array;
|
|
6157
|
+
positions.set(originalPositions);
|
|
6158
|
+
geometry.attributes.position.needsUpdate = true;
|
|
6159
|
+
}
|
|
6160
|
+
const normalsKey = `${geometry.uuid}_normals`;
|
|
6161
|
+
const originalNormals = this.transformedGeometries.get(normalsKey);
|
|
6162
|
+
if (originalNormals && geometry.attributes.normal) {
|
|
6163
|
+
const normals = geometry.attributes.normal.array;
|
|
6164
|
+
normals.set(originalNormals);
|
|
6165
|
+
geometry.attributes.normal.needsUpdate = true;
|
|
6166
|
+
}
|
|
6167
|
+
geometry.computeBoundingSphere();
|
|
6168
|
+
geometry.computeBoundingBox();
|
|
6169
|
+
}
|
|
5884
6170
|
syncHiddenObjects() {
|
|
5885
6171
|
if (this.mergedObjectMap.size === 0) {
|
|
5886
6172
|
console.log("No merged objects to sync");
|
|
@@ -5912,19 +6198,33 @@ class DynamicGltfLoader {
|
|
|
5912
6198
|
}
|
|
5913
6199
|
getStructureGeometryExtent(structureId) {
|
|
5914
6200
|
const extent = new Box3();
|
|
6201
|
+
const structureRoot = this.structureRoots.get(structureId);
|
|
5915
6202
|
for (const [nodeId, node] of this.nodes.entries()) {
|
|
5916
6203
|
if (!node.geometryExtents) continue;
|
|
5917
6204
|
if (!nodeId.startsWith(structureId + "_")) continue;
|
|
5918
6205
|
if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
|
|
5919
6206
|
const transformedBox = node.geometryExtents.clone();
|
|
5920
|
-
if (node.group
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
6207
|
+
if (node.group) {
|
|
6208
|
+
const matrices = [];
|
|
6209
|
+
let currentGroup = node.group;
|
|
6210
|
+
while (currentGroup && currentGroup !== structureRoot) {
|
|
6211
|
+
if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
|
|
6212
|
+
matrices.unshift(currentGroup.matrix);
|
|
6213
|
+
}
|
|
6214
|
+
currentGroup = currentGroup.parent;
|
|
5924
6215
|
}
|
|
6216
|
+
for (const matrix of matrices) {
|
|
6217
|
+
transformedBox.applyMatrix4(matrix);
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
if (structureRoot && structureRoot.matrix) {
|
|
6221
|
+
transformedBox.applyMatrix4(structureRoot.matrix);
|
|
5925
6222
|
}
|
|
5926
6223
|
extent.union(transformedBox);
|
|
5927
6224
|
}
|
|
6225
|
+
if (this.scene && this.scene.matrix && !extent.isEmpty()) {
|
|
6226
|
+
extent.applyMatrix4(this.scene.matrix);
|
|
6227
|
+
}
|
|
5928
6228
|
return extent;
|
|
5929
6229
|
}
|
|
5930
6230
|
setMaxConcurrentChunks(maxChunks) {
|
|
@@ -6497,8 +6797,8 @@ class Viewer extends EventEmitter2 {
|
|
|
6497
6797
|
const rect = canvas.parentElement.getBoundingClientRect();
|
|
6498
6798
|
const width = rect.width || 1;
|
|
6499
6799
|
const height = rect.height || 1;
|
|
6500
|
-
const
|
|
6501
|
-
this.camera = new PerspectiveCamera(45,
|
|
6800
|
+
const aspectRatio = width / height;
|
|
6801
|
+
this.camera = new PerspectiveCamera(45, aspectRatio, 0.001, 1000);
|
|
6502
6802
|
this.camera.up.set(0, 1, 0);
|
|
6503
6803
|
this.camera.position.set(0, 0, 1);
|
|
6504
6804
|
this.camera.lookAt(this.target);
|
|
@@ -6595,14 +6895,14 @@ class Viewer extends EventEmitter2 {
|
|
|
6595
6895
|
if (!this.renderer)
|
|
6596
6896
|
return;
|
|
6597
6897
|
const camera = this.camera;
|
|
6598
|
-
const
|
|
6898
|
+
const aspectRatio = width / height;
|
|
6599
6899
|
if (camera.isPerspectiveCamera) {
|
|
6600
|
-
camera.aspect =
|
|
6900
|
+
camera.aspect = aspectRatio;
|
|
6601
6901
|
camera.updateProjectionMatrix();
|
|
6602
6902
|
}
|
|
6603
6903
|
if (camera.isOrthographicCamera) {
|
|
6604
|
-
camera.left = camera.bottom *
|
|
6605
|
-
camera.right = camera.top *
|
|
6904
|
+
camera.left = camera.bottom * aspectRatio;
|
|
6905
|
+
camera.right = camera.top * aspectRatio;
|
|
6606
6906
|
camera.updateProjectionMatrix();
|
|
6607
6907
|
}
|
|
6608
6908
|
this.renderer.setSize(width, height, updateStyle);
|
|
@@ -6829,12 +7129,12 @@ class Viewer extends EventEmitter2 {
|
|
|
6829
7129
|
if (orthogonal_camera) {
|
|
6830
7130
|
const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
|
|
6831
7131
|
const rendererSize = this.renderer.getSize(new Vector2());
|
|
6832
|
-
const
|
|
7132
|
+
const aspectRatio = rendererSize.x / rendererSize.y;
|
|
6833
7133
|
const camera = new OrthographicCamera();
|
|
6834
7134
|
camera.top = orthogonal_camera.field_height / 2;
|
|
6835
7135
|
camera.bottom = -orthogonal_camera.field_height / 2;
|
|
6836
|
-
camera.left = camera.bottom *
|
|
6837
|
-
camera.right = camera.top *
|
|
7136
|
+
camera.left = camera.bottom * aspectRatio;
|
|
7137
|
+
camera.right = camera.top * aspectRatio;
|
|
6838
7138
|
camera.near = 0;
|
|
6839
7139
|
camera.far = extentsSize * 1000;
|
|
6840
7140
|
camera.zoom = orthogonal_camera.view_to_world_scale;
|
|
@@ -6847,6 +7147,7 @@ class Viewer extends EventEmitter2 {
|
|
|
6847
7147
|
this.renderPass.camera = camera;
|
|
6848
7148
|
this.helpersPass.camera = camera;
|
|
6849
7149
|
this.ssaaRenderPass.camera = camera;
|
|
7150
|
+
this.options.cameraMode = "orthographic";
|
|
6850
7151
|
this.emitEvent({ type: "changecameramode", mode: "orthographic" });
|
|
6851
7152
|
}
|
|
6852
7153
|
};
|
|
@@ -6854,10 +7155,10 @@ class Viewer extends EventEmitter2 {
|
|
|
6854
7155
|
if (perspective_camera) {
|
|
6855
7156
|
const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
|
|
6856
7157
|
const rendererSize = this.renderer.getSize(new Vector2());
|
|
6857
|
-
const
|
|
7158
|
+
const aspectRatio = rendererSize.x / rendererSize.y;
|
|
6858
7159
|
const camera = new PerspectiveCamera();
|
|
6859
7160
|
camera.fov = perspective_camera.field_of_view;
|
|
6860
|
-
camera.aspect =
|
|
7161
|
+
camera.aspect = aspectRatio;
|
|
6861
7162
|
camera.near = extentsSize / 1000;
|
|
6862
7163
|
camera.far = extentsSize * 1000;
|
|
6863
7164
|
camera.updateProjectionMatrix();
|
|
@@ -6869,6 +7170,7 @@ class Viewer extends EventEmitter2 {
|
|
|
6869
7170
|
this.renderPass.camera = camera;
|
|
6870
7171
|
this.helpersPass.camera = camera;
|
|
6871
7172
|
this.ssaaRenderPass.camera = camera;
|
|
7173
|
+
this.options.cameraMode = "perspective";
|
|
6872
7174
|
this.emitEvent({ type: "changecameramode", mode: "perspective" });
|
|
6873
7175
|
}
|
|
6874
7176
|
};
|
|
@@ -6898,6 +7200,7 @@ class Viewer extends EventEmitter2 {
|
|
|
6898
7200
|
setSelection(((_b = viewpoint.custom_fields) === null || _b === void 0 ? void 0 : _b.selection2) || viewpoint.selection);
|
|
6899
7201
|
this._markup.setViewpoint(viewpoint);
|
|
6900
7202
|
this.target.copy(getVector3FromPoint3d((_d = (_c = viewpoint.custom_fields) === null || _c === void 0 ? void 0 : _c.camera_target) !== null && _d !== void 0 ? _d : this.target));
|
|
7203
|
+
this.syncOverlay();
|
|
6901
7204
|
this.setActiveDragger(draggerName);
|
|
6902
7205
|
this.emitEvent({ type: "drawviewpoint", data: viewpoint });
|
|
6903
7206
|
this.update();
|