@inweb/viewer-three 26.12.6 → 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 +457 -155
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +455 -153
- 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/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/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/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) {
|
|
@@ -2489,15 +2498,15 @@ class CameraComponent {
|
|
|
2489
2498
|
switchCamera(camera) {
|
|
2490
2499
|
const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2 || 1;
|
|
2491
2500
|
const rendererSize = this.viewer.renderer.getSize(new Vector2());
|
|
2492
|
-
const
|
|
2501
|
+
const aspectRatio = rendererSize.x / rendererSize.y;
|
|
2493
2502
|
if (camera.isPerspectiveCamera) {
|
|
2494
|
-
camera.aspect =
|
|
2503
|
+
camera.aspect = aspectRatio;
|
|
2495
2504
|
camera.near = extentsSize / 1000;
|
|
2496
2505
|
camera.far = extentsSize * 1000;
|
|
2497
2506
|
}
|
|
2498
2507
|
if (camera.isOrthographicCamera) {
|
|
2499
|
-
camera.left = camera.bottom *
|
|
2500
|
-
camera.right = camera.top *
|
|
2508
|
+
camera.left = camera.bottom * aspectRatio;
|
|
2509
|
+
camera.right = camera.top * aspectRatio;
|
|
2501
2510
|
camera.near = 0;
|
|
2502
2511
|
camera.far = extentsSize * 1000;
|
|
2503
2512
|
}
|
|
@@ -2545,10 +2554,12 @@ class CameraComponent {
|
|
|
2545
2554
|
|
|
2546
2555
|
class ExtentsComponent {
|
|
2547
2556
|
constructor(viewer) {
|
|
2548
|
-
this.syncExtents = () => {
|
|
2557
|
+
this.syncExtents = (event) => {
|
|
2549
2558
|
const extents = new Box3();
|
|
2550
2559
|
this.viewer.models.forEach((model) => model.getExtents(extents));
|
|
2551
2560
|
this.viewer.extents.copy(extents);
|
|
2561
|
+
if (event.type !== "databasechunk" && event.target !== "clear")
|
|
2562
|
+
return;
|
|
2552
2563
|
if (this.viewer.models.length > 1)
|
|
2553
2564
|
return;
|
|
2554
2565
|
this.viewer.extents.getCenter(this.viewer.target);
|
|
@@ -2915,12 +2926,12 @@ class HighlighterComponent {
|
|
|
2915
2926
|
const { edgesVisibility } = this.viewer.options;
|
|
2916
2927
|
if (!Array.isArray(objects))
|
|
2917
2928
|
objects = [objects];
|
|
2918
|
-
if (
|
|
2929
|
+
if (objects.length === 0)
|
|
2919
2930
|
return;
|
|
2920
2931
|
objects
|
|
2921
2932
|
.filter((object) => !object.userData.isEdge)
|
|
2922
2933
|
.forEach((object) => {
|
|
2923
|
-
if (object.isHighlighted)
|
|
2934
|
+
if (object.userData.isHighlighted)
|
|
2924
2935
|
return;
|
|
2925
2936
|
if (object.isLine || object.isLineSegments) {
|
|
2926
2937
|
const positions = object.geometry.attributes.position.array;
|
|
@@ -2929,43 +2940,39 @@ class HighlighterComponent {
|
|
|
2929
2940
|
? HighlighterUtils.fromIndexedLine(positions, indices)
|
|
2930
2941
|
: HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
|
|
2931
2942
|
const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
|
|
2932
|
-
wireframe.position.copy(object.position);
|
|
2933
|
-
wireframe.rotation.copy(object.rotation);
|
|
2934
|
-
wireframe.scale.copy(object.scale);
|
|
2935
2943
|
wireframe.visible = edgesVisibility;
|
|
2936
|
-
|
|
2944
|
+
wireframe.userData.isHighlightWireframe = true;
|
|
2945
|
+
object.add(wireframe);
|
|
2937
2946
|
object.userData.highlightWireframe = wireframe;
|
|
2938
2947
|
object.userData.originalMaterial = object.material;
|
|
2939
2948
|
object.material = this.lineMaterial;
|
|
2940
|
-
object.isHighlighted = true;
|
|
2949
|
+
object.userData.isHighlighted = true;
|
|
2941
2950
|
}
|
|
2942
2951
|
else if (object.isMesh) {
|
|
2943
2952
|
const edgesGeometry = new EdgesGeometry(object.geometry, 89);
|
|
2944
2953
|
const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
|
|
2945
2954
|
const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
|
|
2946
|
-
wireframe.position.copy(object.position);
|
|
2947
|
-
wireframe.rotation.copy(object.rotation);
|
|
2948
|
-
wireframe.scale.copy(object.scale);
|
|
2949
2955
|
wireframe.visible = edgesVisibility;
|
|
2950
|
-
|
|
2956
|
+
wireframe.userData.isHighlightWireframe = true;
|
|
2957
|
+
object.add(wireframe);
|
|
2951
2958
|
object.userData.highlightWireframe = wireframe;
|
|
2952
2959
|
object.userData.originalMaterial = object.material;
|
|
2953
2960
|
object.material = this.facesMaterial;
|
|
2954
|
-
object.isHighlighted = true;
|
|
2961
|
+
object.userData.isHighlighted = true;
|
|
2955
2962
|
}
|
|
2956
2963
|
});
|
|
2957
2964
|
}
|
|
2958
2965
|
unhighlight(objects) {
|
|
2959
2966
|
if (!Array.isArray(objects))
|
|
2960
2967
|
objects = [objects];
|
|
2961
|
-
if (
|
|
2968
|
+
if (objects.length === 0)
|
|
2962
2969
|
return;
|
|
2963
2970
|
objects.forEach((object) => {
|
|
2964
|
-
if (!object.isHighlighted)
|
|
2971
|
+
if (!object.userData.isHighlighted)
|
|
2965
2972
|
return;
|
|
2966
|
-
object.isHighlighted = false;
|
|
2967
2973
|
object.material = object.userData.originalMaterial;
|
|
2968
2974
|
object.userData.highlightWireframe.removeFromParent();
|
|
2975
|
+
delete object.userData.isHighlighted;
|
|
2969
2976
|
delete object.userData.originalMaterial;
|
|
2970
2977
|
delete object.userData.highlightWireframe;
|
|
2971
2978
|
});
|
|
@@ -3013,6 +3020,7 @@ class SelectionComponent {
|
|
|
3013
3020
|
if (upPosition.distanceTo(this.downPosition) !== 0)
|
|
3014
3021
|
return;
|
|
3015
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;
|
|
3016
3024
|
let intersections = [];
|
|
3017
3025
|
this.viewer.models.forEach((model) => {
|
|
3018
3026
|
const objects = model.getVisibleObjects();
|
|
@@ -3067,12 +3075,12 @@ class SelectionComponent {
|
|
|
3067
3075
|
}
|
|
3068
3076
|
if (!Array.isArray(objects))
|
|
3069
3077
|
objects = [objects];
|
|
3070
|
-
if (
|
|
3078
|
+
if (objects.length === 0)
|
|
3071
3079
|
return;
|
|
3072
|
-
model.
|
|
3080
|
+
model.highlightObjects(objects);
|
|
3073
3081
|
this.highlighter.highlight(objects);
|
|
3074
3082
|
objects.forEach((object) => this.viewer.selected.push(object));
|
|
3075
|
-
objects.forEach((object) => (object.isSelected = true));
|
|
3083
|
+
objects.forEach((object) => (object.userData.isSelected = true));
|
|
3076
3084
|
}
|
|
3077
3085
|
deselect(objects, model) {
|
|
3078
3086
|
if (!model) {
|
|
@@ -3081,29 +3089,29 @@ class SelectionComponent {
|
|
|
3081
3089
|
}
|
|
3082
3090
|
if (!Array.isArray(objects))
|
|
3083
3091
|
objects = [objects];
|
|
3084
|
-
if (
|
|
3092
|
+
if (objects.length === 0)
|
|
3085
3093
|
return;
|
|
3094
|
+
model.unhighlightObjects(objects);
|
|
3086
3095
|
this.highlighter.unhighlight(objects);
|
|
3087
|
-
model.hideOriginalObjects(objects);
|
|
3088
3096
|
this.viewer.selected = this.viewer.selected.filter((x) => !objects.includes(x));
|
|
3089
|
-
objects.forEach((object) => (object.isSelected = false));
|
|
3097
|
+
objects.forEach((object) => (object.userData.isSelected = false));
|
|
3090
3098
|
}
|
|
3091
3099
|
toggleSelection(objects, model) {
|
|
3092
3100
|
if (!Array.isArray(objects))
|
|
3093
3101
|
objects = [objects];
|
|
3094
|
-
if (
|
|
3102
|
+
if (objects.length === 0)
|
|
3095
3103
|
return;
|
|
3096
|
-
if (objects[0].isSelected)
|
|
3104
|
+
if (objects[0].userData.isSelected)
|
|
3097
3105
|
this.deselect(objects, model);
|
|
3098
3106
|
else
|
|
3099
3107
|
this.select(objects, model);
|
|
3100
3108
|
}
|
|
3101
3109
|
clearSelection() {
|
|
3102
|
-
if (
|
|
3110
|
+
if (this.viewer.selected.length === 0)
|
|
3103
3111
|
return;
|
|
3112
|
+
this.viewer.models.forEach((model) => model.unhighlightObjects(this.viewer.selected));
|
|
3104
3113
|
this.highlighter.unhighlight(this.viewer.selected);
|
|
3105
|
-
this.viewer.
|
|
3106
|
-
this.viewer.selected.forEach((object) => (object.isSelected = false));
|
|
3114
|
+
this.viewer.selected.forEach((object) => (object.userData.isSelected = false));
|
|
3107
3115
|
this.viewer.selected.length = 0;
|
|
3108
3116
|
}
|
|
3109
3117
|
}
|
|
@@ -3265,6 +3273,20 @@ components.registerComponent("ResetComponent", (viewer) => new ResetComponent(vi
|
|
|
3265
3273
|
class ModelImpl {
|
|
3266
3274
|
constructor(scene) {
|
|
3267
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
|
+
});
|
|
3268
3290
|
}
|
|
3269
3291
|
dispose() {
|
|
3270
3292
|
function disposeMaterial(material) {
|
|
@@ -3280,6 +3302,8 @@ class ModelImpl {
|
|
|
3280
3302
|
if (object.material)
|
|
3281
3303
|
disposeMaterials(object.material);
|
|
3282
3304
|
}
|
|
3305
|
+
this.handleToObjects = undefined;
|
|
3306
|
+
this.originalObjects = undefined;
|
|
3283
3307
|
this.scene.traverse(disposeObject);
|
|
3284
3308
|
this.scene.clear();
|
|
3285
3309
|
}
|
|
@@ -3422,67 +3446,56 @@ class ModelImpl {
|
|
|
3422
3446
|
return info;
|
|
3423
3447
|
}
|
|
3424
3448
|
getExtents(target) {
|
|
3425
|
-
this.scene.traverseVisible((object) =>
|
|
3449
|
+
this.scene.traverseVisible((object) => target.expandByObject(object));
|
|
3426
3450
|
return target;
|
|
3427
3451
|
}
|
|
3428
3452
|
getObjects() {
|
|
3429
|
-
|
|
3430
|
-
this.scene.traverse((object) => objects.push(object));
|
|
3431
|
-
return objects;
|
|
3453
|
+
return Array.from(this.originalObjects);
|
|
3432
3454
|
}
|
|
3433
3455
|
getVisibleObjects() {
|
|
3434
3456
|
const objects = [];
|
|
3435
3457
|
this.scene.traverseVisible((object) => objects.push(object));
|
|
3436
|
-
return objects;
|
|
3437
|
-
}
|
|
3438
|
-
hasObject(object) {
|
|
3439
|
-
while (object) {
|
|
3440
|
-
if (object === this.scene)
|
|
3441
|
-
return true;
|
|
3442
|
-
object = object.parent;
|
|
3443
|
-
}
|
|
3444
|
-
return false;
|
|
3445
|
-
}
|
|
3446
|
-
hasHandle(handle) {
|
|
3447
|
-
return !handle.includes(":") || handle.split(":", 1)[0] === this.id + "";
|
|
3458
|
+
return objects.filter((object) => object.userData.handle);
|
|
3448
3459
|
}
|
|
3449
|
-
|
|
3450
|
-
if (!Array.isArray(objects))
|
|
3451
|
-
objects = [objects];
|
|
3452
|
-
return objects.filter((object) => this.hasObject(object));
|
|
3453
|
-
}
|
|
3454
|
-
getOwnHandles(handles) {
|
|
3460
|
+
getObjectsByHandles(handles) {
|
|
3455
3461
|
if (!Array.isArray(handles))
|
|
3456
3462
|
handles = [handles];
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
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);
|
|
3464
3474
|
const objects = [];
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
if (handle && handleSet.has(handle))
|
|
3468
|
-
objects.push(object);
|
|
3475
|
+
handlesSet.forEach((handle) => {
|
|
3476
|
+
objects.push(Array.from(this.handleToObjects.get(handle) || []));
|
|
3469
3477
|
});
|
|
3470
|
-
return objects;
|
|
3478
|
+
return objects.flat();
|
|
3471
3479
|
}
|
|
3472
3480
|
getHandlesByObjects(objects) {
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
return [];
|
|
3481
|
+
if (!Array.isArray(objects))
|
|
3482
|
+
objects = [objects];
|
|
3476
3483
|
const handleSet = new Set();
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3484
|
+
objects
|
|
3485
|
+
.filter((object) => this.originalObjects.has(object))
|
|
3486
|
+
.forEach((object) => {
|
|
3487
|
+
handleSet.add(`${this.id}:${object.userData.handle}`);
|
|
3481
3488
|
});
|
|
3482
3489
|
return Array.from(handleSet);
|
|
3483
3490
|
}
|
|
3484
3491
|
hideObjects(objects) {
|
|
3485
|
-
|
|
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
|
+
});
|
|
3486
3499
|
return this;
|
|
3487
3500
|
}
|
|
3488
3501
|
hideAllObjects() {
|
|
@@ -3492,12 +3505,20 @@ class ModelImpl {
|
|
|
3492
3505
|
if (!Array.isArray(objects))
|
|
3493
3506
|
objects = [objects];
|
|
3494
3507
|
const visibleSet = new Set(objects);
|
|
3495
|
-
|
|
3508
|
+
objects
|
|
3509
|
+
.filter((object) => this.originalObjects.has(object))
|
|
3510
|
+
.forEach((object) => {
|
|
3511
|
+
object.traverseAncestors((parent) => visibleSet.add(parent));
|
|
3512
|
+
});
|
|
3496
3513
|
this.scene.traverse((object) => (object.visible = visibleSet.has(object)));
|
|
3497
3514
|
return this;
|
|
3498
3515
|
}
|
|
3499
3516
|
showObjects(objects) {
|
|
3500
|
-
|
|
3517
|
+
if (!Array.isArray(objects))
|
|
3518
|
+
objects = [objects];
|
|
3519
|
+
objects
|
|
3520
|
+
.filter((object) => this.originalObjects.has(object))
|
|
3521
|
+
.forEach((object) => {
|
|
3501
3522
|
object.visible = true;
|
|
3502
3523
|
object.traverseAncestors((parent) => (parent.visible = true));
|
|
3503
3524
|
});
|
|
@@ -3507,36 +3528,55 @@ class ModelImpl {
|
|
|
3507
3528
|
this.scene.traverse((object) => (object.visible = true));
|
|
3508
3529
|
return this;
|
|
3509
3530
|
}
|
|
3510
|
-
|
|
3531
|
+
highlightObjects(objects) {
|
|
3511
3532
|
return this;
|
|
3512
3533
|
}
|
|
3513
|
-
|
|
3534
|
+
unhighlightObjects(objects) {
|
|
3514
3535
|
return this;
|
|
3515
3536
|
}
|
|
3516
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
|
+
};
|
|
3517
3553
|
function calcExplodeDepth(object, depth) {
|
|
3518
|
-
let
|
|
3554
|
+
let result = depth;
|
|
3519
3555
|
object.children.forEach((x) => {
|
|
3520
3556
|
const objectDepth = calcExplodeDepth(x, depth + 1);
|
|
3521
|
-
if (
|
|
3522
|
-
|
|
3557
|
+
if (result < objectDepth)
|
|
3558
|
+
result = objectDepth;
|
|
3523
3559
|
});
|
|
3524
3560
|
object.userData.originalPosition = object.position.clone();
|
|
3525
|
-
object.userData.originalCenter =
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
if (!
|
|
3531
|
-
|
|
3532
|
-
const maxDepth =
|
|
3533
|
-
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;
|
|
3534
3570
|
const explodeDepth = 0 | scaledExplodeDepth;
|
|
3535
3571
|
const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
|
|
3536
3572
|
function explodeObject(object, depth) {
|
|
3573
|
+
if (object.isCamera)
|
|
3574
|
+
return;
|
|
3575
|
+
if (object.userData.isHighlightWireframe)
|
|
3576
|
+
return;
|
|
3537
3577
|
object.position.copy(object.userData.originalPosition);
|
|
3538
|
-
if (depth > 0 && depth <= explodeDepth
|
|
3539
|
-
let objectScale =
|
|
3578
|
+
if (depth > 0 && depth <= explodeDepth) {
|
|
3579
|
+
let objectScale = explodeScale * coeff;
|
|
3540
3580
|
if (depth === explodeDepth)
|
|
3541
3581
|
objectScale *= currentSegmentFraction;
|
|
3542
3582
|
const parentCenter = object.parent.userData.originalCenter;
|
|
@@ -3546,7 +3586,7 @@ class ModelImpl {
|
|
|
3546
3586
|
}
|
|
3547
3587
|
object.children.forEach((x) => explodeObject(x, depth + 1));
|
|
3548
3588
|
}
|
|
3549
|
-
explodeObject(
|
|
3589
|
+
explodeObject(explodeRoot, 0);
|
|
3550
3590
|
this.scene.updateMatrixWorld();
|
|
3551
3591
|
return this;
|
|
3552
3592
|
}
|
|
@@ -3584,29 +3624,24 @@ class DynamicModelImpl extends ModelImpl {
|
|
|
3584
3624
|
getVisibleObjects() {
|
|
3585
3625
|
return this.gltfLoader.getOriginalObjectForSelect();
|
|
3586
3626
|
}
|
|
3587
|
-
hasObject(object) {
|
|
3588
|
-
return this.gltfLoader.originalObjects.has(object);
|
|
3589
|
-
}
|
|
3590
3627
|
getObjectsByHandles(handles) {
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
const handlesSet = new Set(ownHandles);
|
|
3628
|
+
if (!Array.isArray(handles))
|
|
3629
|
+
handles = [handles];
|
|
3630
|
+
const handlesSet = new Set(handles);
|
|
3595
3631
|
const objects = [];
|
|
3596
3632
|
handlesSet.forEach((handle) => {
|
|
3597
|
-
objects.push(
|
|
3633
|
+
objects.push(this.gltfLoader.getObjectsByHandle(handle));
|
|
3598
3634
|
});
|
|
3599
|
-
return objects;
|
|
3635
|
+
return objects.flat();
|
|
3600
3636
|
}
|
|
3601
3637
|
getHandlesByObjects(objects) {
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
return [];
|
|
3638
|
+
if (!Array.isArray(objects))
|
|
3639
|
+
objects = [objects];
|
|
3605
3640
|
const handleSet = new Set();
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3641
|
+
objects
|
|
3642
|
+
.filter((object) => this.gltfLoader.originalObjects.has(object))
|
|
3643
|
+
.forEach((object) => {
|
|
3644
|
+
handleSet.add(object.userData.handle);
|
|
3610
3645
|
});
|
|
3611
3646
|
return Array.from(handleSet);
|
|
3612
3647
|
}
|
|
@@ -3629,14 +3664,78 @@ class DynamicModelImpl extends ModelImpl {
|
|
|
3629
3664
|
this.gltfLoader.showAllHiddenObjects();
|
|
3630
3665
|
return this;
|
|
3631
3666
|
}
|
|
3632
|
-
|
|
3667
|
+
highlightObjects(objects) {
|
|
3633
3668
|
this.gltfLoader.showOriginalObjects(objects);
|
|
3634
3669
|
return this;
|
|
3635
3670
|
}
|
|
3636
|
-
|
|
3671
|
+
unhighlightObjects(objects) {
|
|
3637
3672
|
this.gltfLoader.hideOriginalObjects(objects);
|
|
3638
3673
|
return this;
|
|
3639
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
|
+
}
|
|
3640
3739
|
}
|
|
3641
3740
|
|
|
3642
3741
|
const GL_COMPONENT_TYPES = {
|
|
@@ -3685,7 +3784,7 @@ class GltfStructure {
|
|
|
3685
3784
|
this.textureCache = new Map();
|
|
3686
3785
|
this.materialCache = new Map();
|
|
3687
3786
|
this.uri = "";
|
|
3688
|
-
this._nextObjectId =
|
|
3787
|
+
this._nextObjectId = 1;
|
|
3689
3788
|
this.loadingAborted = false;
|
|
3690
3789
|
this.criticalError = null;
|
|
3691
3790
|
}
|
|
@@ -4204,6 +4303,8 @@ class DynamicGltfLoader {
|
|
|
4204
4303
|
this.hiddenHandles = new Set();
|
|
4205
4304
|
this.newOptimizedObjects = new Set();
|
|
4206
4305
|
this.oldOptimizeObjects = new Set();
|
|
4306
|
+
this.objectTransforms = new Map();
|
|
4307
|
+
this.transformedGeometries = new Map();
|
|
4207
4308
|
this.activeChunkLoads = 0;
|
|
4208
4309
|
this.chunkQueue = [];
|
|
4209
4310
|
this.objectIdToIndex = new Map();
|
|
@@ -4965,14 +5066,32 @@ class DynamicGltfLoader {
|
|
|
4965
5066
|
if (!node.geometryExtents) continue;
|
|
4966
5067
|
if (node.object && this.hiddenHandles.has(node.object.userData.handle)) continue;
|
|
4967
5068
|
const transformedBox = node.geometryExtents.clone();
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
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;
|
|
4972
5078
|
}
|
|
5079
|
+
for (const matrix of matrices) {
|
|
5080
|
+
transformedBox.applyMatrix4(matrix);
|
|
5081
|
+
}
|
|
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);
|
|
4973
5089
|
}
|
|
4974
5090
|
totalExtent.union(transformedBox);
|
|
4975
5091
|
}
|
|
5092
|
+
if (this.scene && this.scene.matrix && !totalExtent.isEmpty()) {
|
|
5093
|
+
totalExtent.applyMatrix4(this.scene.matrix);
|
|
5094
|
+
}
|
|
4976
5095
|
return totalExtent;
|
|
4977
5096
|
}
|
|
4978
5097
|
loadCamera(structure, cameraIndex, nodeDef) {
|
|
@@ -5048,7 +5167,6 @@ class DynamicGltfLoader {
|
|
|
5048
5167
|
for (let i = 0; i < this.maxObjectId; i++) {
|
|
5049
5168
|
this.objectVisibility[i] = 1.0;
|
|
5050
5169
|
}
|
|
5051
|
-
console.log(`Initialized object visibility array: ${this.maxObjectId} objects`);
|
|
5052
5170
|
}
|
|
5053
5171
|
}
|
|
5054
5172
|
createVisibilityMaterial(material) {
|
|
@@ -5185,6 +5303,8 @@ class DynamicGltfLoader {
|
|
|
5185
5303
|
this.newOptimizedObjects.clear();
|
|
5186
5304
|
this.oldOptimizeObjects.clear();
|
|
5187
5305
|
this.isolatedObjects = [];
|
|
5306
|
+
this.objectTransforms.clear();
|
|
5307
|
+
this.transformedGeometries.clear();
|
|
5188
5308
|
this.totalLoadedObjects = 0;
|
|
5189
5309
|
this.lastUpdateTime = 0;
|
|
5190
5310
|
this.currentMemoryUsage = 0;
|
|
@@ -5882,6 +6002,171 @@ class DynamicGltfLoader {
|
|
|
5882
6002
|
mergedObject.geometry.attributes.visibility.needsUpdate = true;
|
|
5883
6003
|
}
|
|
5884
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
|
+
}
|
|
5885
6170
|
syncHiddenObjects() {
|
|
5886
6171
|
if (this.mergedObjectMap.size === 0) {
|
|
5887
6172
|
console.log("No merged objects to sync");
|
|
@@ -5913,19 +6198,33 @@ class DynamicGltfLoader {
|
|
|
5913
6198
|
}
|
|
5914
6199
|
getStructureGeometryExtent(structureId) {
|
|
5915
6200
|
const extent = new Box3();
|
|
6201
|
+
const structureRoot = this.structureRoots.get(structureId);
|
|
5916
6202
|
for (const [nodeId, node] of this.nodes.entries()) {
|
|
5917
6203
|
if (!node.geometryExtents) continue;
|
|
5918
6204
|
if (!nodeId.startsWith(structureId + "_")) continue;
|
|
5919
6205
|
if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
|
|
5920
6206
|
const transformedBox = node.geometryExtents.clone();
|
|
5921
|
-
if (node.group
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
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;
|
|
5925
6215
|
}
|
|
6216
|
+
for (const matrix of matrices) {
|
|
6217
|
+
transformedBox.applyMatrix4(matrix);
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
if (structureRoot && structureRoot.matrix) {
|
|
6221
|
+
transformedBox.applyMatrix4(structureRoot.matrix);
|
|
5926
6222
|
}
|
|
5927
6223
|
extent.union(transformedBox);
|
|
5928
6224
|
}
|
|
6225
|
+
if (this.scene && this.scene.matrix && !extent.isEmpty()) {
|
|
6226
|
+
extent.applyMatrix4(this.scene.matrix);
|
|
6227
|
+
}
|
|
5929
6228
|
return extent;
|
|
5930
6229
|
}
|
|
5931
6230
|
setMaxConcurrentChunks(maxChunks) {
|
|
@@ -6498,8 +6797,8 @@ class Viewer extends EventEmitter2 {
|
|
|
6498
6797
|
const rect = canvas.parentElement.getBoundingClientRect();
|
|
6499
6798
|
const width = rect.width || 1;
|
|
6500
6799
|
const height = rect.height || 1;
|
|
6501
|
-
const
|
|
6502
|
-
this.camera = new PerspectiveCamera(45,
|
|
6800
|
+
const aspectRatio = width / height;
|
|
6801
|
+
this.camera = new PerspectiveCamera(45, aspectRatio, 0.001, 1000);
|
|
6503
6802
|
this.camera.up.set(0, 1, 0);
|
|
6504
6803
|
this.camera.position.set(0, 0, 1);
|
|
6505
6804
|
this.camera.lookAt(this.target);
|
|
@@ -6596,14 +6895,14 @@ class Viewer extends EventEmitter2 {
|
|
|
6596
6895
|
if (!this.renderer)
|
|
6597
6896
|
return;
|
|
6598
6897
|
const camera = this.camera;
|
|
6599
|
-
const
|
|
6898
|
+
const aspectRatio = width / height;
|
|
6600
6899
|
if (camera.isPerspectiveCamera) {
|
|
6601
|
-
camera.aspect =
|
|
6900
|
+
camera.aspect = aspectRatio;
|
|
6602
6901
|
camera.updateProjectionMatrix();
|
|
6603
6902
|
}
|
|
6604
6903
|
if (camera.isOrthographicCamera) {
|
|
6605
|
-
camera.left = camera.bottom *
|
|
6606
|
-
camera.right = camera.top *
|
|
6904
|
+
camera.left = camera.bottom * aspectRatio;
|
|
6905
|
+
camera.right = camera.top * aspectRatio;
|
|
6607
6906
|
camera.updateProjectionMatrix();
|
|
6608
6907
|
}
|
|
6609
6908
|
this.renderer.setSize(width, height, updateStyle);
|
|
@@ -6830,12 +7129,12 @@ class Viewer extends EventEmitter2 {
|
|
|
6830
7129
|
if (orthogonal_camera) {
|
|
6831
7130
|
const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
|
|
6832
7131
|
const rendererSize = this.renderer.getSize(new Vector2());
|
|
6833
|
-
const
|
|
7132
|
+
const aspectRatio = rendererSize.x / rendererSize.y;
|
|
6834
7133
|
const camera = new OrthographicCamera();
|
|
6835
7134
|
camera.top = orthogonal_camera.field_height / 2;
|
|
6836
7135
|
camera.bottom = -orthogonal_camera.field_height / 2;
|
|
6837
|
-
camera.left = camera.bottom *
|
|
6838
|
-
camera.right = camera.top *
|
|
7136
|
+
camera.left = camera.bottom * aspectRatio;
|
|
7137
|
+
camera.right = camera.top * aspectRatio;
|
|
6839
7138
|
camera.near = 0;
|
|
6840
7139
|
camera.far = extentsSize * 1000;
|
|
6841
7140
|
camera.zoom = orthogonal_camera.view_to_world_scale;
|
|
@@ -6848,6 +7147,7 @@ class Viewer extends EventEmitter2 {
|
|
|
6848
7147
|
this.renderPass.camera = camera;
|
|
6849
7148
|
this.helpersPass.camera = camera;
|
|
6850
7149
|
this.ssaaRenderPass.camera = camera;
|
|
7150
|
+
this.options.cameraMode = "orthographic";
|
|
6851
7151
|
this.emitEvent({ type: "changecameramode", mode: "orthographic" });
|
|
6852
7152
|
}
|
|
6853
7153
|
};
|
|
@@ -6855,10 +7155,10 @@ class Viewer extends EventEmitter2 {
|
|
|
6855
7155
|
if (perspective_camera) {
|
|
6856
7156
|
const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
|
|
6857
7157
|
const rendererSize = this.renderer.getSize(new Vector2());
|
|
6858
|
-
const
|
|
7158
|
+
const aspectRatio = rendererSize.x / rendererSize.y;
|
|
6859
7159
|
const camera = new PerspectiveCamera();
|
|
6860
7160
|
camera.fov = perspective_camera.field_of_view;
|
|
6861
|
-
camera.aspect =
|
|
7161
|
+
camera.aspect = aspectRatio;
|
|
6862
7162
|
camera.near = extentsSize / 1000;
|
|
6863
7163
|
camera.far = extentsSize * 1000;
|
|
6864
7164
|
camera.updateProjectionMatrix();
|
|
@@ -6870,6 +7170,7 @@ class Viewer extends EventEmitter2 {
|
|
|
6870
7170
|
this.renderPass.camera = camera;
|
|
6871
7171
|
this.helpersPass.camera = camera;
|
|
6872
7172
|
this.ssaaRenderPass.camera = camera;
|
|
7173
|
+
this.options.cameraMode = "perspective";
|
|
6873
7174
|
this.emitEvent({ type: "changecameramode", mode: "perspective" });
|
|
6874
7175
|
}
|
|
6875
7176
|
};
|
|
@@ -6899,6 +7200,7 @@ class Viewer extends EventEmitter2 {
|
|
|
6899
7200
|
setSelection(((_b = viewpoint.custom_fields) === null || _b === void 0 ? void 0 : _b.selection2) || viewpoint.selection);
|
|
6900
7201
|
this._markup.setViewpoint(viewpoint);
|
|
6901
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();
|
|
6902
7204
|
this.setActiveDragger(draggerName);
|
|
6903
7205
|
this.emitEvent({ type: "drawviewpoint", data: viewpoint });
|
|
6904
7206
|
this.update();
|