@inweb/viewer-three 26.7.2 → 26.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/viewer-three.js +386 -246
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +4 -2
- package/dist/viewer-three.module.js +340 -161
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/components/HighlighterComponent.d.ts +2 -2
- package/lib/Viewer/loaders/GLTFCloudDynamicLoader.d.ts +0 -2
- package/lib/Viewer/loaders/index.d.ts +1 -1
- package/package.json +5 -5
- package/src/Viewer/Viewer.ts +6 -1
- package/src/Viewer/commands/SetSelected.ts +1 -0
- package/src/Viewer/commands/index.ts +1 -1
- package/src/Viewer/components/CameraComponent.ts +0 -1
- package/src/Viewer/components/HighlighterComponent.ts +38 -16
- package/src/Viewer/components/LightComponent.ts +11 -15
- package/src/Viewer/components/SelectionComponent.ts +1 -2
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +187 -65
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +7 -12
- package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +120 -114
- package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +7 -13
- package/src/Viewer/loaders/index.ts +1 -1
|
@@ -2,7 +2,7 @@ import { draggersRegistry, commandsRegistry, componentsRegistry, Loader, loaders
|
|
|
2
2
|
|
|
3
3
|
export * from "@inweb/viewer-core";
|
|
4
4
|
|
|
5
|
-
import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Matrix4, Vector4, Raycaster, Controls, Clock, Sphere, MathUtils, Box3, Color, AmbientLight, DirectionalLight, HemisphereLight, WebGLRenderTarget, UnsignedByteType, RGBAFormat, EdgesGeometry, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, LoadingManager, LoaderUtils, TextureLoader, BufferAttribute,
|
|
5
|
+
import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Matrix4, Vector4, Raycaster, Controls, Clock, Sphere, MathUtils, Box3, Color, AmbientLight, DirectionalLight, HemisphereLight, MeshPhongMaterial, WebGLRenderTarget, UnsignedByteType, RGBAFormat, EdgesGeometry, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, LoadingManager, LoaderUtils, TextureLoader, BufferAttribute, PointsMaterial, Material, Points, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, LineLoop, Group, NormalBlending, MeshStandardMaterial, PerspectiveCamera, Scene, WebGLRenderer, LinearToneMapping } from "three";
|
|
6
6
|
|
|
7
7
|
import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
|
|
8
8
|
|
|
@@ -1676,6 +1676,7 @@ function setSelected(viewer, handles = []) {
|
|
|
1676
1676
|
selection.clearSelection();
|
|
1677
1677
|
viewer.models.forEach((model => {
|
|
1678
1678
|
const objects = model.getObjectsByHandles(handles);
|
|
1679
|
+
model.showObjects(objects);
|
|
1679
1680
|
selection.select(objects, model);
|
|
1680
1681
|
}));
|
|
1681
1682
|
viewer.update();
|
|
@@ -1729,12 +1730,12 @@ commands.registerCommand("clearSelected", clearSelected);
|
|
|
1729
1730
|
|
|
1730
1731
|
commands.registerCommand("clearSlices", clearSlices);
|
|
1731
1732
|
|
|
1733
|
+
commands.registerCommand("collect", collect);
|
|
1734
|
+
|
|
1732
1735
|
commands.registerCommand("createPreview", createPreview);
|
|
1733
1736
|
|
|
1734
1737
|
commands.registerCommand("explode", explode);
|
|
1735
1738
|
|
|
1736
|
-
commands.registerCommand("collect", collect);
|
|
1737
|
-
|
|
1738
1739
|
commands.registerCommand("getDefaultViewPositions", getDefaultViewPositions);
|
|
1739
1740
|
|
|
1740
1741
|
commands.registerCommand("getModels", getModels);
|
|
@@ -1844,7 +1845,6 @@ class CameraComponent {
|
|
|
1844
1845
|
}));
|
|
1845
1846
|
if (sceneCamera) {
|
|
1846
1847
|
this.viewer.camera = sceneCamera.clone();
|
|
1847
|
-
this.viewer.camera.up.set(0, 0, 1);
|
|
1848
1848
|
this.viewer.camera.scale.set(1, 1, 1);
|
|
1849
1849
|
}
|
|
1850
1850
|
const camera = this.viewer.camera;
|
|
@@ -1911,11 +1911,11 @@ class LightComponent {
|
|
|
1911
1911
|
if (this.viewer.extents.isEmpty()) return;
|
|
1912
1912
|
const extentsCenter = this.viewer.extents.getCenter(new Vector3);
|
|
1913
1913
|
const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere).radius;
|
|
1914
|
-
this.directionalLight.position.set(.5,
|
|
1914
|
+
this.directionalLight.position.set(.5, .866, 0).multiplyScalar(extentsSize * 2).add(extentsCenter);
|
|
1915
1915
|
this.directionalLight.target.position.copy(extentsCenter);
|
|
1916
|
-
this.frontLight.position.set(0, extentsSize * 2
|
|
1916
|
+
this.frontLight.position.set(0, 0, 1).multiplyScalar(extentsSize * 2).add(extentsCenter);
|
|
1917
1917
|
this.frontLight.target.position.copy(extentsCenter);
|
|
1918
|
-
this.hemisphereLight.position.set(0, extentsSize * 3
|
|
1918
|
+
this.hemisphereLight.position.set(0, 0, 1).multiplyScalar(extentsSize * 3).add(extentsCenter);
|
|
1919
1919
|
this.viewer.scene.add(this.ambientLight);
|
|
1920
1920
|
this.viewer.scene.add(this.directionalLight);
|
|
1921
1921
|
this.viewer.scene.add(this.frontLight);
|
|
@@ -1923,16 +1923,9 @@ class LightComponent {
|
|
|
1923
1923
|
};
|
|
1924
1924
|
this.viewer = viewer;
|
|
1925
1925
|
this.ambientLight = new AmbientLight(16777215, 1);
|
|
1926
|
-
this.viewer.scene.add(this.ambientLight);
|
|
1927
1926
|
this.directionalLight = new DirectionalLight(16777215, 1);
|
|
1928
|
-
this.directionalLight.position.set(.5, 0, .866);
|
|
1929
|
-
this.viewer.scene.add(this.directionalLight);
|
|
1930
1927
|
this.frontLight = new DirectionalLight(16777215, 1.25);
|
|
1931
|
-
this.frontLight.position.set(0, 1, 0);
|
|
1932
|
-
this.viewer.scene.add(this.frontLight);
|
|
1933
1928
|
this.hemisphereLight = new HemisphereLight(16777215, 4473924, 1.25);
|
|
1934
|
-
this.hemisphereLight.position.set(0, 0, 1);
|
|
1935
|
-
this.viewer.scene.add(this.hemisphereLight);
|
|
1936
1929
|
this.viewer.addEventListener("databasechunk", this.geometryEnd);
|
|
1937
1930
|
this.viewer.addEventListener("clear", this.geometryEnd);
|
|
1938
1931
|
}
|
|
@@ -2051,19 +2044,25 @@ class HighlighterUtils {
|
|
|
2051
2044
|
class HighlighterComponent {
|
|
2052
2045
|
constructor(viewer) {
|
|
2053
2046
|
this.geometryEnd = () => {
|
|
2054
|
-
const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor} = this.viewer.options;
|
|
2055
|
-
this.highlightMaterial = new
|
|
2047
|
+
const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor, edgesOverlap: edgesOverlap, facesOverlap: facesOverlap} = this.viewer.options;
|
|
2048
|
+
this.highlightMaterial = new MeshPhongMaterial({
|
|
2056
2049
|
color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
|
|
2057
2050
|
transparent: true,
|
|
2058
2051
|
opacity: (255 - facesTransparancy) / 255,
|
|
2059
|
-
depthTest:
|
|
2060
|
-
depthWrite:
|
|
2052
|
+
depthTest: !facesOverlap,
|
|
2053
|
+
depthWrite: !facesOverlap,
|
|
2054
|
+
specular: 2236962,
|
|
2055
|
+
shininess: 10,
|
|
2056
|
+
reflectivity: .05,
|
|
2057
|
+
polygonOffset: true,
|
|
2058
|
+
polygonOffsetFactor: 1,
|
|
2059
|
+
polygonOffsetUnits: 1
|
|
2061
2060
|
});
|
|
2062
2061
|
this.outlineMaterial = new LineMaterial({
|
|
2063
2062
|
color: new Color(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255),
|
|
2064
2063
|
linewidth: 1.5,
|
|
2065
|
-
depthTest:
|
|
2066
|
-
depthWrite:
|
|
2064
|
+
depthTest: !edgesOverlap,
|
|
2065
|
+
depthWrite: !edgesOverlap,
|
|
2067
2066
|
resolution: new Vector2(window.innerWidth, window.innerHeight)
|
|
2068
2067
|
});
|
|
2069
2068
|
this.highlightLineMaterial = new LineBasicMaterial({
|
|
@@ -2076,18 +2075,26 @@ class HighlighterComponent {
|
|
|
2076
2075
|
linewidth: 5,
|
|
2077
2076
|
transparent: true,
|
|
2078
2077
|
opacity: .8,
|
|
2079
|
-
depthTest:
|
|
2080
|
-
depthWrite:
|
|
2078
|
+
depthTest: !edgesOverlap,
|
|
2079
|
+
depthWrite: !edgesOverlap,
|
|
2081
2080
|
resolution: new Vector2(window.innerWidth, window.innerHeight)
|
|
2082
2081
|
});
|
|
2083
2082
|
};
|
|
2084
2083
|
this.optionsChange = () => {
|
|
2085
|
-
const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor} = this.viewer.options;
|
|
2084
|
+
const {facesColor: facesColor, facesTransparancy: facesTransparancy, edgesColor: edgesColor, edgesVisibility: edgesVisibility, edgesOverlap: edgesOverlap, facesOverlap: facesOverlap} = this.viewer.options;
|
|
2086
2085
|
this.highlightMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
2087
2086
|
this.highlightMaterial.opacity = (255 - facesTransparancy) / 255;
|
|
2087
|
+
this.highlightMaterial.depthTest = !facesOverlap;
|
|
2088
|
+
this.highlightMaterial.depthWrite = !facesOverlap;
|
|
2088
2089
|
this.outlineMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
|
|
2090
|
+
this.outlineMaterial.depthTest = !edgesOverlap;
|
|
2091
|
+
this.outlineMaterial.depthWrite = !edgesOverlap;
|
|
2089
2092
|
this.highlightLineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
2090
2093
|
this.highlightLineGlowMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
|
|
2094
|
+
this.viewer.selected.forEach((selected => {
|
|
2095
|
+
const wireframe = selected.userData.highlightWireframe;
|
|
2096
|
+
if (wireframe) wireframe.visible = edgesVisibility;
|
|
2097
|
+
}));
|
|
2091
2098
|
this.viewer.update();
|
|
2092
2099
|
};
|
|
2093
2100
|
this.viewer = viewer;
|
|
@@ -2112,6 +2119,7 @@ class HighlighterComponent {
|
|
|
2112
2119
|
this.viewer.removeEventListener("resize", this.viewerResize);
|
|
2113
2120
|
}
|
|
2114
2121
|
highlight(objects) {
|
|
2122
|
+
const {edgesVisibility: edgesVisibility} = this.viewer.options;
|
|
2115
2123
|
if (!Array.isArray(objects)) objects = [ objects ];
|
|
2116
2124
|
if (!objects.length) return;
|
|
2117
2125
|
objects.forEach((object => {
|
|
@@ -2124,20 +2132,22 @@ class HighlighterComponent {
|
|
|
2124
2132
|
wireframe.position.copy(object.position);
|
|
2125
2133
|
wireframe.rotation.copy(object.rotation);
|
|
2126
2134
|
wireframe.scale.copy(object.scale);
|
|
2135
|
+
wireframe.visible = edgesVisibility;
|
|
2127
2136
|
object.parent.add(wireframe);
|
|
2128
|
-
object.userData.
|
|
2137
|
+
object.userData.highlightWireframe = wireframe;
|
|
2129
2138
|
object.userData.originalMaterial = object.material;
|
|
2130
2139
|
object.material = this.highlightLineMaterial;
|
|
2131
2140
|
object.isHighlighted = true;
|
|
2132
2141
|
} else if (object.isMesh) {
|
|
2133
|
-
const edgesGeometry = new EdgesGeometry(object.geometry,
|
|
2142
|
+
const edgesGeometry = new EdgesGeometry(object.geometry, 60);
|
|
2134
2143
|
const lineGeometry = (new LineSegmentsGeometry).fromEdgesGeometry(edgesGeometry);
|
|
2135
2144
|
const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
|
|
2136
2145
|
wireframe.position.copy(object.position);
|
|
2137
2146
|
wireframe.rotation.copy(object.rotation);
|
|
2138
2147
|
wireframe.scale.copy(object.scale);
|
|
2148
|
+
wireframe.visible = edgesVisibility;
|
|
2139
2149
|
object.parent.add(wireframe);
|
|
2140
|
-
object.userData.
|
|
2150
|
+
object.userData.highlightWireframe = wireframe;
|
|
2141
2151
|
object.userData.originalMaterial = object.material;
|
|
2142
2152
|
object.material = this.highlightMaterial;
|
|
2143
2153
|
object.isHighlighted = true;
|
|
@@ -2151,9 +2161,9 @@ class HighlighterComponent {
|
|
|
2151
2161
|
if (!object.isHighlighted) return;
|
|
2152
2162
|
object.isHighlighted = false;
|
|
2153
2163
|
object.material = object.userData.originalMaterial;
|
|
2154
|
-
object.userData.
|
|
2164
|
+
object.userData.highlightWireframe.removeFromParent();
|
|
2155
2165
|
delete object.userData.originalMaterial;
|
|
2156
|
-
delete object.userData.
|
|
2166
|
+
delete object.userData.highlightWireframe;
|
|
2157
2167
|
}));
|
|
2158
2168
|
}
|
|
2159
2169
|
viewerResize(event) {
|
|
@@ -2177,10 +2187,10 @@ class SelectionComponent {
|
|
|
2177
2187
|
this.viewer.models.forEach((model => {
|
|
2178
2188
|
const objects = model.getVisibleObjects();
|
|
2179
2189
|
const intersects = this.getPointerIntersects(upPosition, objects);
|
|
2180
|
-
|
|
2181
|
-
...
|
|
2190
|
+
if (intersects.length > 0) intersections.push({
|
|
2191
|
+
...intersects[0],
|
|
2182
2192
|
model: model
|
|
2183
|
-
})
|
|
2193
|
+
});
|
|
2184
2194
|
}));
|
|
2185
2195
|
intersections = intersections.sort(((a, b) => a.distance - b.distance));
|
|
2186
2196
|
if (!event.shiftKey) this.clearSelection();
|
|
@@ -2250,7 +2260,6 @@ class SelectionComponent {
|
|
|
2250
2260
|
}
|
|
2251
2261
|
if (!Array.isArray(objects)) objects = [ objects ];
|
|
2252
2262
|
if (!objects.length) return;
|
|
2253
|
-
model.showObjects(objects);
|
|
2254
2263
|
model.showOriginalObjects(objects);
|
|
2255
2264
|
this.highlighter.highlight(objects);
|
|
2256
2265
|
objects.forEach((object => this.viewer.selected.push(object)));
|
|
@@ -2634,8 +2643,8 @@ class DynamicModelImpl extends ModelImpl {
|
|
|
2634
2643
|
return objects;
|
|
2635
2644
|
}
|
|
2636
2645
|
hideObjects(objects) {
|
|
2637
|
-
|
|
2638
|
-
this.gltfLoader.
|
|
2646
|
+
const handles = this.getHandlesByObjects(objects);
|
|
2647
|
+
this.gltfLoader.hideObjects(handles);
|
|
2639
2648
|
return this;
|
|
2640
2649
|
}
|
|
2641
2650
|
isolateObjects(objects) {
|
|
@@ -2644,21 +2653,20 @@ class DynamicModelImpl extends ModelImpl {
|
|
|
2644
2653
|
return this;
|
|
2645
2654
|
}
|
|
2646
2655
|
showObjects(objects) {
|
|
2647
|
-
|
|
2648
|
-
this.gltfLoader.
|
|
2656
|
+
const handles = this.getHandlesByObjects(objects);
|
|
2657
|
+
this.gltfLoader.showObjects(handles);
|
|
2649
2658
|
return this;
|
|
2650
2659
|
}
|
|
2651
2660
|
showAllObjects() {
|
|
2652
|
-
this.gltfLoader.
|
|
2653
|
-
this.gltfLoader.syncHiddenObjects();
|
|
2661
|
+
this.gltfLoader.showAllHiddenObjects();
|
|
2654
2662
|
return this;
|
|
2655
2663
|
}
|
|
2656
2664
|
showOriginalObjects(objects) {
|
|
2657
|
-
this.
|
|
2665
|
+
this.gltfLoader.showOriginalObjects(objects);
|
|
2658
2666
|
return this;
|
|
2659
2667
|
}
|
|
2660
2668
|
hideOriginalObjects(objects) {
|
|
2661
|
-
this.
|
|
2669
|
+
this.gltfLoader.hideOriginalObjects(objects);
|
|
2662
2670
|
return this;
|
|
2663
2671
|
}
|
|
2664
2672
|
}
|
|
@@ -2682,6 +2690,10 @@ const GL_CONSTANTS = {
|
|
|
2682
2690
|
TRIANGLE_FAN: 6
|
|
2683
2691
|
};
|
|
2684
2692
|
|
|
2693
|
+
const MAX_GAP = 128 * 1024;
|
|
2694
|
+
|
|
2695
|
+
const MAX_CHUNK = 30 * 1024 * 1024;
|
|
2696
|
+
|
|
2685
2697
|
class GltfStructure {
|
|
2686
2698
|
constructor(id) {
|
|
2687
2699
|
this.id = `${id}`;
|
|
@@ -2719,42 +2731,99 @@ class GltfStructure {
|
|
|
2719
2731
|
return this.json;
|
|
2720
2732
|
}
|
|
2721
2733
|
scheduleRequest(request) {
|
|
2722
|
-
this.pendingRequests.push(request);
|
|
2723
|
-
if (this.batchTimeout) {
|
|
2724
|
-
clearTimeout(this.batchTimeout);
|
|
2725
|
-
}
|
|
2726
|
-
this.batchTimeout = setTimeout((() => this.processBatch()), this.batchDelay);
|
|
2727
2734
|
return new Promise(((resolve, reject) => {
|
|
2728
|
-
|
|
2729
|
-
|
|
2735
|
+
this.pendingRequests.push({
|
|
2736
|
+
...request,
|
|
2737
|
+
_resolve: resolve,
|
|
2738
|
+
_reject: reject
|
|
2739
|
+
});
|
|
2730
2740
|
}));
|
|
2731
2741
|
}
|
|
2732
|
-
async
|
|
2733
|
-
if (this.pendingRequests.length === 0) return;
|
|
2734
|
-
const
|
|
2742
|
+
async flushBufferRequests() {
|
|
2743
|
+
if (!this.pendingRequests || this.pendingRequests.length === 0) return;
|
|
2744
|
+
const requests = [ ...this.pendingRequests ];
|
|
2735
2745
|
this.pendingRequests = [];
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2746
|
+
requests.sort(((a, b) => a.offset - b.offset));
|
|
2747
|
+
const mergedRanges = [];
|
|
2748
|
+
let current = {
|
|
2749
|
+
start: requests[0].offset,
|
|
2750
|
+
end: requests[0].offset + requests[0].length,
|
|
2751
|
+
requests: [ requests[0] ]
|
|
2752
|
+
};
|
|
2753
|
+
for (let i = 1; i < requests.length; i++) {
|
|
2754
|
+
const req = requests[i];
|
|
2755
|
+
const gap = req.offset - current.end;
|
|
2756
|
+
const newEnd = Math.max(current.end, req.offset + req.length);
|
|
2757
|
+
const projectedSize = newEnd - current.start;
|
|
2758
|
+
if (gap <= MAX_GAP && projectedSize <= MAX_CHUNK) {
|
|
2759
|
+
current.end = newEnd;
|
|
2760
|
+
current.requests.push(req);
|
|
2761
|
+
} else {
|
|
2762
|
+
mergedRanges.push(current);
|
|
2763
|
+
current = {
|
|
2764
|
+
start: req.offset,
|
|
2765
|
+
end: req.offset + req.length,
|
|
2766
|
+
requests: [ req ]
|
|
2767
|
+
};
|
|
2750
2768
|
}
|
|
2751
|
-
} catch (error) {
|
|
2752
|
-
console.error("Error processing batch:", error);
|
|
2753
|
-
currentBatch.forEach((request => request.reject(error)));
|
|
2754
2769
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2770
|
+
mergedRanges.push(current);
|
|
2771
|
+
const finalRanges = [];
|
|
2772
|
+
for (const range of mergedRanges) {
|
|
2773
|
+
let {start: start, end: end, requests: requests} = range;
|
|
2774
|
+
while (end - start > MAX_CHUNK) {
|
|
2775
|
+
let splitIdx = 0;
|
|
2776
|
+
for (let i = 0; i < requests.length; i++) {
|
|
2777
|
+
if (requests[i].offset + requests[i].length - start > MAX_CHUNK) {
|
|
2778
|
+
break;
|
|
2779
|
+
}
|
|
2780
|
+
splitIdx = i;
|
|
2781
|
+
}
|
|
2782
|
+
const chunkRequests = requests.slice(0, splitIdx + 1);
|
|
2783
|
+
const chunkEnd = chunkRequests[chunkRequests.length - 1].offset + chunkRequests[chunkRequests.length - 1].length;
|
|
2784
|
+
finalRanges.push({
|
|
2785
|
+
start: start,
|
|
2786
|
+
end: chunkEnd,
|
|
2787
|
+
requests: chunkRequests
|
|
2788
|
+
});
|
|
2789
|
+
requests = requests.slice(splitIdx + 1);
|
|
2790
|
+
if (requests.length > 0) {
|
|
2791
|
+
start = requests[0].offset;
|
|
2792
|
+
end = requests[0].offset + requests[0].length;
|
|
2793
|
+
for (let i = 1; i < requests.length; i++) {
|
|
2794
|
+
end = Math.max(end, requests[i].offset + requests[i].length);
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
if (requests.length > 0) {
|
|
2799
|
+
finalRanges.push({
|
|
2800
|
+
start: start,
|
|
2801
|
+
end: end,
|
|
2802
|
+
requests: requests
|
|
2803
|
+
});
|
|
2804
|
+
}
|
|
2757
2805
|
}
|
|
2806
|
+
const promises = finalRanges.map((async range => {
|
|
2807
|
+
const length = range.end - range.start;
|
|
2808
|
+
const buffer = await this.loadController.loadBinaryData([ {
|
|
2809
|
+
offset: range.start,
|
|
2810
|
+
length: length
|
|
2811
|
+
} ]);
|
|
2812
|
+
for (const req of range.requests) {
|
|
2813
|
+
const relOffset = req.offset - range.start;
|
|
2814
|
+
try {
|
|
2815
|
+
req._resolve({
|
|
2816
|
+
buffer: buffer,
|
|
2817
|
+
relOffset: relOffset,
|
|
2818
|
+
length: req.length
|
|
2819
|
+
});
|
|
2820
|
+
} catch (e) {
|
|
2821
|
+
req._reject(e);
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
}));
|
|
2825
|
+
await Promise.all(promises);
|
|
2826
|
+
this.pendingRequests = [];
|
|
2758
2827
|
}
|
|
2759
2828
|
getBufferView(byteOffset, byteLength, componentType) {
|
|
2760
2829
|
return this.scheduleRequest({
|
|
@@ -2913,62 +2982,48 @@ class GltfStructure {
|
|
|
2913
2982
|
}
|
|
2914
2983
|
await Promise.all(texturePromises);
|
|
2915
2984
|
}
|
|
2916
|
-
loadMaterials() {
|
|
2985
|
+
async loadMaterials() {
|
|
2917
2986
|
if (!this.json.materials) return this.materials;
|
|
2918
2987
|
for (let i = 0; i < this.json.materials.length; i++) {
|
|
2919
2988
|
const materialDef = this.json.materials[i];
|
|
2920
|
-
const material = this.createMaterial(materialDef);
|
|
2989
|
+
const material = await this.createMaterial(materialDef);
|
|
2990
|
+
material.name = materialDef.name;
|
|
2921
2991
|
this.materials.set(i, material);
|
|
2922
2992
|
}
|
|
2923
2993
|
return this.materials;
|
|
2924
2994
|
}
|
|
2925
2995
|
createMaterial(materialDef) {
|
|
2926
|
-
const
|
|
2996
|
+
const params = {};
|
|
2927
2997
|
if (materialDef.pbrMetallicRoughness) {
|
|
2928
2998
|
const pbr = materialDef.pbrMetallicRoughness;
|
|
2929
2999
|
if (pbr.baseColorFactor) {
|
|
2930
|
-
|
|
2931
|
-
|
|
3000
|
+
params.color = (new Color).fromArray(pbr.baseColorFactor);
|
|
3001
|
+
params.opacity = pbr.baseColorFactor[3];
|
|
3002
|
+
if (params.opacity < 1) params.transparent = true;
|
|
2932
3003
|
}
|
|
2933
3004
|
if (pbr.baseColorTexture) {
|
|
2934
|
-
|
|
2935
|
-
}
|
|
2936
|
-
if (pbr.metallicFactor !== undefined) {
|
|
2937
|
-
material.metalness = pbr.metallicFactor;
|
|
2938
|
-
}
|
|
2939
|
-
if (pbr.roughnessFactor !== undefined) {
|
|
2940
|
-
material.roughness = pbr.roughnessFactor;
|
|
2941
|
-
}
|
|
2942
|
-
if (pbr.metallicRoughnessTexture) {
|
|
2943
|
-
material.metalnessMap = this.textureCache.get(pbr.metallicRoughnessTexture.index);
|
|
2944
|
-
material.roughnessMap = material.metalnessMap;
|
|
2945
|
-
}
|
|
2946
|
-
}
|
|
2947
|
-
if (materialDef.normalTexture) {
|
|
2948
|
-
material.normalMap = this.textureCache.get(materialDef.normalTexture.index);
|
|
2949
|
-
if (materialDef.normalTexture.scale !== undefined) {
|
|
2950
|
-
material.normalScale.set(materialDef.normalTexture.scale, materialDef.normalTexture.scale);
|
|
3005
|
+
params.map = this.textureCache.get(pbr.baseColorTexture.index);
|
|
2951
3006
|
}
|
|
2952
3007
|
}
|
|
3008
|
+
params.specular = 2236962;
|
|
3009
|
+
params.shininess = 10;
|
|
3010
|
+
params.reflectivity = .05;
|
|
3011
|
+
params.polygonOffset = true;
|
|
3012
|
+
params.polygonOffsetFactor = 1;
|
|
3013
|
+
params.polygonOffsetUnits = 1;
|
|
2953
3014
|
if (materialDef.emissiveFactor) {
|
|
2954
|
-
|
|
3015
|
+
params.emissive = (new Color).fromArray(materialDef.emissiveFactor);
|
|
2955
3016
|
}
|
|
2956
|
-
if (materialDef.
|
|
2957
|
-
|
|
2958
|
-
}
|
|
2959
|
-
if (materialDef.occlusionTexture) {
|
|
2960
|
-
material.aoMap = this.textureCache.get(materialDef.occlusionTexture.index);
|
|
2961
|
-
if (materialDef.occlusionTexture.strength !== undefined) {
|
|
2962
|
-
material.aoMapIntensity = materialDef.occlusionTexture.strength;
|
|
2963
|
-
}
|
|
3017
|
+
if (materialDef.normalTexture) {
|
|
3018
|
+
params.normalMap = this.textureCache.get(materialDef.normalTexture.index);
|
|
2964
3019
|
}
|
|
2965
3020
|
if (materialDef.alphaMode === "BLEND") {
|
|
2966
|
-
|
|
2967
|
-
} else if (materialDef.alphaMode === "MASK") {
|
|
2968
|
-
material.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : .5;
|
|
3021
|
+
params.transparent = true;
|
|
2969
3022
|
}
|
|
2970
|
-
|
|
2971
|
-
|
|
3023
|
+
if (materialDef.doubleSided) {
|
|
3024
|
+
params.side = DoubleSide;
|
|
3025
|
+
}
|
|
3026
|
+
const material = new MeshPhongMaterial(params);
|
|
2972
3027
|
return material;
|
|
2973
3028
|
}
|
|
2974
3029
|
disposeMaterials() {
|
|
@@ -3213,12 +3268,17 @@ class DynamicGltfLoader {
|
|
|
3213
3268
|
this.mergedLineSegments = new Set;
|
|
3214
3269
|
this.mergedPoints = new Set;
|
|
3215
3270
|
this.isolatedObjects = [];
|
|
3216
|
-
|
|
3271
|
+
//!!window.WebGL2RenderingContext && this.renderer.getContext() instanceof WebGL2RenderingContext
|
|
3272
|
+
this.useVAO = false;
|
|
3273
|
+
this.visibleEdges = true;
|
|
3217
3274
|
this.handleToOptimizedObjects = new Map;
|
|
3218
3275
|
this.hiddenHandles = new Set;
|
|
3219
3276
|
this.newOptimizedObjects = new Set;
|
|
3220
3277
|
this.oldOptimizeObjects = new Set;
|
|
3221
3278
|
}
|
|
3279
|
+
setVisibleEdges(visible) {
|
|
3280
|
+
this.visibleEdges = visible;
|
|
3281
|
+
}
|
|
3222
3282
|
getAvailableMemory() {
|
|
3223
3283
|
let memoryLimit = 6 * 1024 * 1024 * 1024;
|
|
3224
3284
|
try {
|
|
@@ -3236,7 +3296,7 @@ class DynamicGltfLoader {
|
|
|
3236
3296
|
} catch (error) {
|
|
3237
3297
|
console.warn("Error detecting available memory:", error);
|
|
3238
3298
|
}
|
|
3239
|
-
return memoryLimit;
|
|
3299
|
+
return memoryLimit / 3;
|
|
3240
3300
|
}
|
|
3241
3301
|
getAbortController() {
|
|
3242
3302
|
return this.abortController;
|
|
@@ -3317,35 +3377,132 @@ class DynamicGltfLoader {
|
|
|
3317
3377
|
this.updateMemoryIndicator();
|
|
3318
3378
|
console.log(`Final memory usage: ${Math.round(currentMemoryUsage / (1024 * 1024))}MB`);
|
|
3319
3379
|
}
|
|
3320
|
-
async loadNode(nodeId) {
|
|
3380
|
+
async loadNode(nodeId, onLoadFinishCb) {
|
|
3321
3381
|
const node = this.nodes.get(nodeId);
|
|
3322
3382
|
if (!node || node.loaded || node.loading) return;
|
|
3323
3383
|
node.loading = true;
|
|
3324
3384
|
const meshDef = node.structure.getJson().meshes[node.meshIndex];
|
|
3325
3385
|
try {
|
|
3326
|
-
|
|
3327
|
-
|
|
3386
|
+
const bufferRequests = [];
|
|
3387
|
+
const primitiveReqMap = new Map;
|
|
3388
|
+
for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
|
|
3389
|
+
const primitive = meshDef.primitives[primIdx];
|
|
3390
|
+
const reqs = [];
|
|
3391
|
+
if (primitive.attributes.POSITION !== undefined) {
|
|
3392
|
+
const accessorIndex = primitive.attributes.POSITION;
|
|
3393
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
3394
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
3395
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
3396
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
3397
|
+
const count = accessor.count;
|
|
3398
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
3399
|
+
reqs.push({
|
|
3400
|
+
offset: byteOffset,
|
|
3401
|
+
length: byteLength,
|
|
3402
|
+
componentType: accessor.componentType,
|
|
3403
|
+
accessorIndex: accessorIndex,
|
|
3404
|
+
type: "position",
|
|
3405
|
+
primIdx: primIdx
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3408
|
+
if (primitive.attributes.NORMAL !== undefined) {
|
|
3409
|
+
const accessorIndex = primitive.attributes.NORMAL;
|
|
3410
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
3411
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
3412
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
3413
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
3414
|
+
const count = accessor.count;
|
|
3415
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
3416
|
+
reqs.push({
|
|
3417
|
+
offset: byteOffset,
|
|
3418
|
+
length: byteLength,
|
|
3419
|
+
componentType: accessor.componentType,
|
|
3420
|
+
accessorIndex: accessorIndex,
|
|
3421
|
+
type: "normal",
|
|
3422
|
+
primIdx: primIdx
|
|
3423
|
+
});
|
|
3424
|
+
}
|
|
3425
|
+
if (primitive.attributes.TEXCOORD_0 !== undefined) {
|
|
3426
|
+
const accessorIndex = primitive.attributes.TEXCOORD_0;
|
|
3427
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
3428
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
3429
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
3430
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
3431
|
+
const count = accessor.count;
|
|
3432
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
3433
|
+
reqs.push({
|
|
3434
|
+
offset: byteOffset,
|
|
3435
|
+
length: byteLength,
|
|
3436
|
+
componentType: accessor.componentType,
|
|
3437
|
+
accessorIndex: accessorIndex,
|
|
3438
|
+
type: "uv",
|
|
3439
|
+
primIdx: primIdx
|
|
3440
|
+
});
|
|
3441
|
+
}
|
|
3442
|
+
if (primitive.indices !== undefined) {
|
|
3443
|
+
const accessorIndex = primitive.indices;
|
|
3444
|
+
const accessor = node.structure.json.accessors[accessorIndex];
|
|
3445
|
+
const bufferView = node.structure.json.bufferViews[accessor.bufferView];
|
|
3446
|
+
const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
|
|
3447
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
3448
|
+
const count = accessor.count;
|
|
3449
|
+
const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
|
|
3450
|
+
reqs.push({
|
|
3451
|
+
offset: byteOffset,
|
|
3452
|
+
length: byteLength,
|
|
3453
|
+
componentType: accessor.componentType,
|
|
3454
|
+
accessorIndex: accessorIndex,
|
|
3455
|
+
type: "index",
|
|
3456
|
+
primIdx: primIdx
|
|
3457
|
+
});
|
|
3458
|
+
}
|
|
3459
|
+
primitiveReqMap.set(primIdx, reqs);
|
|
3460
|
+
bufferRequests.push(...reqs);
|
|
3461
|
+
}
|
|
3462
|
+
if (bufferRequests.length === 0) {
|
|
3463
|
+
node.loaded = true;
|
|
3464
|
+
node.loading = false;
|
|
3465
|
+
return;
|
|
3466
|
+
}
|
|
3467
|
+
bufferRequests.sort(((a, b) => a.offset - b.offset));
|
|
3468
|
+
const minOffset = bufferRequests[0].offset;
|
|
3469
|
+
const maxOffset = Math.max(...bufferRequests.map((r => r.offset + r.length)));
|
|
3470
|
+
const totalLength = maxOffset - minOffset;
|
|
3471
|
+
const {buffer: buffer, relOffset: baseRelOffset} = await node.structure.scheduleRequest({
|
|
3472
|
+
offset: minOffset,
|
|
3473
|
+
length: totalLength,
|
|
3474
|
+
componentType: null
|
|
3475
|
+
});
|
|
3476
|
+
for (const req of bufferRequests) {
|
|
3477
|
+
const relOffset = req.offset - minOffset;
|
|
3478
|
+
req.data = node.structure.createTypedArray(buffer, baseRelOffset + relOffset, req.length, req.componentType);
|
|
3479
|
+
}
|
|
3480
|
+
for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
|
|
3481
|
+
const primitive = meshDef.primitives[primIdx];
|
|
3328
3482
|
const geometry = new BufferGeometry;
|
|
3329
|
-
const
|
|
3330
|
-
attributes.
|
|
3483
|
+
const reqs = primitiveReqMap.get(primIdx);
|
|
3484
|
+
if (primitive.attributes.POSITION !== undefined) {
|
|
3485
|
+
const req = reqs.find((r => r.type === "position" && r.accessorIndex === primitive.attributes.POSITION));
|
|
3486
|
+
const accessor = node.structure.json.accessors[primitive.attributes.POSITION];
|
|
3487
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
3488
|
+
geometry.setAttribute("position", new BufferAttribute(req.data, components));
|
|
3489
|
+
}
|
|
3331
3490
|
if (primitive.attributes.NORMAL !== undefined) {
|
|
3332
|
-
|
|
3491
|
+
const req = reqs.find((r => r.type === "normal" && r.accessorIndex === primitive.attributes.NORMAL));
|
|
3492
|
+
const accessor = node.structure.json.accessors[primitive.attributes.NORMAL];
|
|
3493
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
3494
|
+
geometry.setAttribute("normal", new BufferAttribute(req.data, components));
|
|
3333
3495
|
}
|
|
3334
3496
|
if (primitive.attributes.TEXCOORD_0 !== undefined) {
|
|
3335
|
-
|
|
3497
|
+
const req = reqs.find((r => r.type === "uv" && r.accessorIndex === primitive.attributes.TEXCOORD_0));
|
|
3498
|
+
const accessor = node.structure.json.accessors[primitive.attributes.TEXCOORD_0];
|
|
3499
|
+
const components = node.structure.getNumComponents(accessor.type);
|
|
3500
|
+
geometry.setAttribute("uv", new BufferAttribute(req.data, components));
|
|
3336
3501
|
}
|
|
3337
|
-
const loadedAttributes = await Promise.all([ ...attributes.entries() ].map((async ([name, promise]) => {
|
|
3338
|
-
const attribute = await promise;
|
|
3339
|
-
return [ name, attribute ];
|
|
3340
|
-
})));
|
|
3341
|
-
loadedAttributes.forEach((([name, attribute]) => {
|
|
3342
|
-
geometry.setAttribute(name, attribute);
|
|
3343
|
-
}));
|
|
3344
3502
|
if (primitive.indices !== undefined) {
|
|
3345
|
-
const
|
|
3346
|
-
geometry.setIndex(
|
|
3503
|
+
const req = reqs.find((r => r.type === "index" && r.accessorIndex === primitive.indices));
|
|
3504
|
+
geometry.setIndex(new BufferAttribute(req.data, 1));
|
|
3347
3505
|
}
|
|
3348
|
-
this.currentPrimitiveMode = primitive.mode;
|
|
3349
3506
|
let material;
|
|
3350
3507
|
if (primitive.material !== undefined) {
|
|
3351
3508
|
material = node.structure.materials.get(primitive.material) || this.createDefaultMaterial();
|
|
@@ -3424,6 +3581,9 @@ class DynamicGltfLoader {
|
|
|
3424
3581
|
const geometrySize = this.estimateGeometrySize(node.object);
|
|
3425
3582
|
this.geometryCache.set(node.object.uuid, geometrySize);
|
|
3426
3583
|
this.currentMemoryUsage += geometrySize;
|
|
3584
|
+
if (onLoadFinishCb) {
|
|
3585
|
+
onLoadFinishCb();
|
|
3586
|
+
}
|
|
3427
3587
|
} catch (error) {
|
|
3428
3588
|
if (error.name !== "AbortError") {
|
|
3429
3589
|
console.error(`Error loading node ${nodeId}:`, error);
|
|
@@ -3521,7 +3681,7 @@ class DynamicGltfLoader {
|
|
|
3521
3681
|
const volumeB = sizeB.x * sizeB.y * sizeB.z;
|
|
3522
3682
|
return volumeB - volumeA;
|
|
3523
3683
|
}));
|
|
3524
|
-
if (!ignoreEdges) {
|
|
3684
|
+
if (!ignoreEdges && this.visibleEdges) {
|
|
3525
3685
|
this.nodesToLoad.push(...this.edgeNodes);
|
|
3526
3686
|
}
|
|
3527
3687
|
this.dispatchEvent("databasechunk", {
|
|
@@ -3629,28 +3789,12 @@ class DynamicGltfLoader {
|
|
|
3629
3789
|
async processNodes() {
|
|
3630
3790
|
const nodesToLoad = this.nodesToLoad;
|
|
3631
3791
|
let loadedCount = 0;
|
|
3792
|
+
let lastLoadedCount = 0;
|
|
3632
3793
|
const totalNodes = nodesToLoad.length;
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
for (const nodeId of batch) {
|
|
3638
|
-
if (this.abortController.signal.aborted) {
|
|
3639
|
-
throw new DOMException("Loading aborted", "AbortError");
|
|
3640
|
-
}
|
|
3641
|
-
const estimatedSize = await this.estimateNodeSize(nodeId);
|
|
3642
|
-
if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
|
|
3643
|
-
console.log(`Memory limit reached after loading ${loadedCount} nodes`);
|
|
3644
|
-
this.dispatchEvent("geometryerror", {
|
|
3645
|
-
message: "Memory limit reached"
|
|
3646
|
-
});
|
|
3647
|
-
this.dispatchEvent("update");
|
|
3648
|
-
return loadedCount;
|
|
3649
|
-
}
|
|
3650
|
-
batchPromises.push(this.loadNode(nodeId));
|
|
3651
|
-
}
|
|
3652
|
-
await Promise.all(batchPromises);
|
|
3653
|
-
loadedCount += batch.length;
|
|
3794
|
+
const loadProgress = async () => {
|
|
3795
|
+
loadedCount++;
|
|
3796
|
+
if (loadedCount - lastLoadedCount > 1e3) {
|
|
3797
|
+
lastLoadedCount = loadedCount;
|
|
3654
3798
|
this.updateMemoryIndicator();
|
|
3655
3799
|
this.dispatchEvent("geometryprogress", {
|
|
3656
3800
|
percentage: Math.round(loadedCount / totalNodes * 100),
|
|
@@ -3666,6 +3810,28 @@ class DynamicGltfLoader {
|
|
|
3666
3810
|
setTimeout(resolve, 0);
|
|
3667
3811
|
}));
|
|
3668
3812
|
}
|
|
3813
|
+
};
|
|
3814
|
+
try {
|
|
3815
|
+
const loadOperations = [];
|
|
3816
|
+
for (const nodeId of nodesToLoad) {
|
|
3817
|
+
if (this.abortController.signal.aborted) {
|
|
3818
|
+
throw new DOMException("Loading aborted", "AbortError");
|
|
3819
|
+
}
|
|
3820
|
+
const estimatedSize = await this.estimateNodeSize(nodeId);
|
|
3821
|
+
if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
|
|
3822
|
+
console.log(`Memory limit reached after loading ${loadedCount} nodes`);
|
|
3823
|
+
this.dispatchEvent("geometryerror", {
|
|
3824
|
+
message: "Memory limit reached"
|
|
3825
|
+
});
|
|
3826
|
+
this.dispatchEvent("update");
|
|
3827
|
+
return loadedCount;
|
|
3828
|
+
}
|
|
3829
|
+
loadOperations.push(this.loadNode(nodeId, loadProgress));
|
|
3830
|
+
}
|
|
3831
|
+
for (const structure of this.structures) {
|
|
3832
|
+
loadOperations.push(structure.flushBufferRequests());
|
|
3833
|
+
}
|
|
3834
|
+
await Promise.all(loadOperations);
|
|
3669
3835
|
this.dispatchEvent("geometryend", {
|
|
3670
3836
|
totalLoaded: loadedCount,
|
|
3671
3837
|
totalNodes: totalNodes
|
|
@@ -4469,13 +4635,29 @@ class DynamicGltfLoader {
|
|
|
4469
4635
|
}
|
|
4470
4636
|
}));
|
|
4471
4637
|
}
|
|
4638
|
+
getStructureGeometryExtent(structureId) {
|
|
4639
|
+
const extent = new Box3;
|
|
4640
|
+
for (const [nodeId, node] of this.nodes.entries()) {
|
|
4641
|
+
if (!node.geometryExtents) continue;
|
|
4642
|
+
if (!nodeId.startsWith(structureId + "_")) continue;
|
|
4643
|
+
if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
|
|
4644
|
+
const transformedBox = node.geometryExtents.clone();
|
|
4645
|
+
if (node.group && node.group.matrix) {
|
|
4646
|
+
transformedBox.applyMatrix4(node.group.matrix);
|
|
4647
|
+
if (node.group.parent && node.group.parent.matrix) {
|
|
4648
|
+
transformedBox.applyMatrix4(node.group.parent.matrix);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
extent.union(transformedBox);
|
|
4652
|
+
}
|
|
4653
|
+
return extent;
|
|
4654
|
+
}
|
|
4472
4655
|
}
|
|
4473
4656
|
|
|
4474
4657
|
class GLTFCloudDynamicLoader {
|
|
4475
4658
|
constructor(viewer) {
|
|
4476
4659
|
this.requestId = 0;
|
|
4477
4660
|
this.viewer = viewer;
|
|
4478
|
-
this.scene = new Group;
|
|
4479
4661
|
}
|
|
4480
4662
|
dispose() {
|
|
4481
4663
|
if (this.gltfLoader) this.gltfLoader.clear();
|
|
@@ -4484,21 +4666,22 @@ class GLTFCloudDynamicLoader {
|
|
|
4484
4666
|
return typeof file === "object" && typeof file.database === "string" && typeof file.downloadResource === "function" && typeof file.downloadResourceRange === "function" && /.gltf$/i.test(file.database);
|
|
4485
4667
|
}
|
|
4486
4668
|
async load(model, format, params) {
|
|
4487
|
-
|
|
4669
|
+
const scene = new Group;
|
|
4670
|
+
this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
|
|
4488
4671
|
this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
|
|
4489
4672
|
this.gltfLoader.addEventListener("databasechunk", (data => {
|
|
4490
|
-
const modelImpl = new DynamicModelImpl(
|
|
4673
|
+
const modelImpl = new DynamicModelImpl(scene);
|
|
4491
4674
|
modelImpl.loader = this;
|
|
4492
4675
|
modelImpl.gltfLoader = this.gltfLoader;
|
|
4493
4676
|
modelImpl.viewer = this.viewer;
|
|
4494
|
-
this.viewer.scene.add(
|
|
4677
|
+
this.viewer.scene.add(scene);
|
|
4495
4678
|
this.viewer.models.push(modelImpl);
|
|
4496
4679
|
this.viewer.syncOptions();
|
|
4497
4680
|
this.viewer.syncOverlay();
|
|
4498
4681
|
this.viewer.update();
|
|
4499
4682
|
this.viewer.emitEvent({
|
|
4500
4683
|
type: "databasechunk",
|
|
4501
|
-
data:
|
|
4684
|
+
data: scene,
|
|
4502
4685
|
file: model.file,
|
|
4503
4686
|
model: model
|
|
4504
4687
|
});
|
|
@@ -4512,12 +4695,6 @@ class GLTFCloudDynamicLoader {
|
|
|
4512
4695
|
model: model
|
|
4513
4696
|
});
|
|
4514
4697
|
}));
|
|
4515
|
-
this.gltfLoader.addEventListener("geometrymemory", (data => {
|
|
4516
|
-
this.viewer.emit({
|
|
4517
|
-
type: "geometryprogress",
|
|
4518
|
-
data: data
|
|
4519
|
-
});
|
|
4520
|
-
}));
|
|
4521
4698
|
this.gltfLoader.addEventListener("geometryerror", (data => {
|
|
4522
4699
|
this.viewer.emitEvent({
|
|
4523
4700
|
type: "geometryerror",
|
|
@@ -4560,9 +4737,7 @@ class GLTFCloudDynamicLoader {
|
|
|
4560
4737
|
return this;
|
|
4561
4738
|
}
|
|
4562
4739
|
cancel() {
|
|
4563
|
-
if (this.gltfLoader)
|
|
4564
|
-
this.gltfLoader.abortLoading();
|
|
4565
|
-
}
|
|
4740
|
+
if (this.gltfLoader) this.gltfLoader.abortLoading();
|
|
4566
4741
|
}
|
|
4567
4742
|
}
|
|
4568
4743
|
|
|
@@ -4607,13 +4782,17 @@ class Viewer extends EventEmitter2 {
|
|
|
4607
4782
|
this.addEventListener("optionschange", (event => this.syncOptions(event.data)));
|
|
4608
4783
|
this.scene = new Scene;
|
|
4609
4784
|
this.helpers = new Scene;
|
|
4785
|
+
this.target = new Vector3;
|
|
4610
4786
|
const pixelRatio = window.devicePixelRatio;
|
|
4611
4787
|
const rect = canvas.parentElement.getBoundingClientRect();
|
|
4612
4788
|
const width = rect.width || 1;
|
|
4613
4789
|
const height = rect.height || 1;
|
|
4614
4790
|
const aspect = width / height;
|
|
4615
4791
|
this.camera = new PerspectiveCamera(45, aspect, .01, 1e3);
|
|
4616
|
-
this.camera.up.set(0,
|
|
4792
|
+
this.camera.up.set(0, 1, 0);
|
|
4793
|
+
this.camera.position.set(0, 0, 1);
|
|
4794
|
+
this.camera.lookAt(this.target);
|
|
4795
|
+
this.camera.updateProjectionMatrix();
|
|
4617
4796
|
this.renderer = new WebGLRenderer({
|
|
4618
4797
|
canvas: canvas,
|
|
4619
4798
|
antialias: true,
|