@xeokit/xeokit-sdk 2.6.73 → 2.6.77-slim-rc1
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/xeokit-sdk.cjs.js +246 -126
- package/dist/xeokit-sdk.es.js +246 -126
- package/dist/xeokit-sdk.es5.js +316 -306
- package/dist/xeokit-sdk.min.cjs.js +8 -8
- package/dist/xeokit-sdk.min.es.js +8 -8
- package/dist/xeokit-sdk.min.es5.js +7 -7
- package/package.json +2 -1
- package/src/extras/ContextMenu/ContextMenu.js +25 -16
- package/src/extras/Skybox/Skybox.js +139 -0
- package/src/extras/index.js +2 -1
- package/src/plugins/CxConverterIFCLoaderPlugin/CxConverterIFCLoaderPlugin.js +81 -81
- package/src/plugins/CxConverterIFCLoaderPlugin/index.js +1 -1
- package/src/plugins/FastNavPlugin/FastNavPlugin.js +10 -18
- package/src/plugins/SectionPlanesPlugin/Control.js +1 -1
- package/src/plugins/TreeViewPlugin/RenderService.js +13 -4
- package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +1 -1
- package/src/plugins/index.js +0 -1
- package/src/viewer/Viewer.js +0 -16
- package/src/viewer/scene/CameraControl/lib/controllers/PivotController.js +29 -8
- package/src/viewer/scene/LineSet/LineSet.js +7 -2
- package/src/viewer/scene/camera/CameraFlightAnimation.js +2 -2
- package/src/viewer/scene/canvas/Canvas.js +7 -4
- package/src/viewer/scene/index.js +0 -1
- package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +5 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js +5 -0
- package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js +5 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorRenderer.js +5 -0
- package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatColorRenderer.js +5 -0
- package/types/plugins/FastNavPlugin/FastNavPlugin.d.ts +5 -0
- package/types/plugins/index.d.ts +0 -1
- package/types/viewer/scene/CameraControl/CameraControl.d.ts +168 -0
- package/types/viewer/scene/LineSet/LineSet.d.ts +1 -1
- package/types/viewer/scene/camera/CameraPath.d.ts +86 -6
- package/types/viewer/scene/camera/CameraPathAnimation.d.ts +2 -0
- package/types/viewer/scene/geometry/ReadableGeometry.d.ts +14 -0
- package/types/viewer/scene/geometry/VBOGeometry.d.ts +2 -0
- package/types/viewer/scene/geometry/index.d.ts +2 -1
- package/types/viewer/scene/geometry/loaders/index.d.ts +2 -0
- package/types/viewer/scene/geometry/loaders/load3DSGeometry.d.ts +17 -0
- package/types/viewer/scene/geometry/loaders/loadOBJGeometry.d.ts +18 -0
- package/types/viewer/scene/index.d.ts +1 -0
- package/types/viewer/scene/input/input.d.ts +117 -0
- package/types/viewer/scene/lights/AmbientLight.d.ts +41 -0
- package/types/viewer/scene/lights/CubeTexture.d.ts +27 -0
- package/types/viewer/scene/lights/DirLight.d.ts +77 -0
- package/types/viewer/scene/lights/LightMap.d.ts +27 -0
- package/types/viewer/scene/lights/PointLight.d.ts +135 -0
- package/types/viewer/scene/lights/ReflectionMap.d.ts +26 -0
- package/types/viewer/scene/lights/index.d.ts +4 -1
- package/types/viewer/scene/marker/Marker.d.ts +5 -0
- package/types/viewer/scene/materials/EmphasisMaterial.d.ts +5 -0
- package/types/viewer/scene/materials/Fresnel.d.ts +25 -62
- package/types/viewer/scene/materials/LambertMaterial.d.ts +192 -0
- package/types/viewer/scene/materials/MetallicMaterial.d.ts +359 -0
- package/types/viewer/scene/materials/PhongMaterial.d.ts +5 -0
- package/types/viewer/scene/materials/PointsMaterial.d.ts +5 -0
- package/types/viewer/scene/materials/SpecularMaterial.d.ts +342 -0
- package/types/viewer/scene/materials/Texture.d.ts +36 -78
- package/types/viewer/scene/materials/index.d.ts +2 -0
- package/types/viewer/scene/models/SceneModel.d.ts +134 -7
- package/types/viewer/scene/models/SceneModelEntity.d.ts +65 -0
- package/types/viewer/scene/models/SceneModelMesh.d.ts +12 -0
- package/types/viewer/scene/paths/CubicBezierCurve.d.ts +146 -0
- package/types/viewer/scene/paths/Curve.d.ts +75 -0
- package/types/viewer/scene/paths/Path.d.ts +119 -0
- package/types/viewer/scene/paths/QuadraticBezierCurve.d.ts +124 -0
- package/types/viewer/scene/paths/SplineCurve.d.ts +84 -0
- package/types/viewer/scene/paths/index.d.ts +5 -0
- package/types/viewer/scene/scene/Scene.d.ts +102 -0
- package/types/viewer/scene/sectionPlane/SectionPlane.d.ts +41 -0
- package/types/viewer/scene/webgl/PickResult.d.ts +19 -0
- package/src/plugins/SkyboxesPlugin/SkyboxesPlugin.js +0 -134
- package/src/plugins/SkyboxesPlugin/index.js +0 -1
- package/src/viewer/scene/skybox/Skybox.js +0 -123
- package/types/plugins/SkyboxesPlugin/SkyboxesPlugin.d.ts +0 -34
- package/types/plugins/SkyboxesPlugin/index.d.ts +0 -1
- /package/src/{viewer/scene/skybox → extras/Skybox}/index.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xeokit/xeokit-sdk",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.77-slim-rc1",
|
|
4
4
|
"description": "3D BIM IFC Viewer SDK for AEC engineering applications. Open Source JavaScript Toolkit based on pure WebGL for top performance, real-world coordinates and full double precision",
|
|
5
5
|
"module": "./dist/xeokit-sdk.es.js",
|
|
6
6
|
"main": "./dist/xeokit-sdk.cjs.js",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"@loaders.gl/core": "^4.3.3",
|
|
58
58
|
"@loaders.gl/gltf": "^4.3.3",
|
|
59
59
|
"@loaders.gl/las": "^4.3.3",
|
|
60
|
+
"@rollup/plugin-replace": "^6.0.2",
|
|
60
61
|
"html2canvas": "^1.4.1"
|
|
61
62
|
},
|
|
62
63
|
"devDependencies": {
|
|
@@ -298,7 +298,8 @@ class ContextMenu {
|
|
|
298
298
|
this._shown = false; // True when the ContextMenu is visible
|
|
299
299
|
this._nextId = 0;
|
|
300
300
|
this._parentNode = cfg.parentNode || document.body;
|
|
301
|
-
|
|
301
|
+
this._offsetParent = (this._parentNode instanceof ShadowRoot) ? this._parentNode.host : this._parentNode;
|
|
302
|
+
|
|
302
303
|
/**
|
|
303
304
|
* Subscriptions to events fired at this ContextMenu.
|
|
304
305
|
* @private
|
|
@@ -510,7 +511,7 @@ class ContextMenu {
|
|
|
510
511
|
for (let i = 0, len = this._menuList.length; i < len; i++) {
|
|
511
512
|
const menu = this._menuList[i];
|
|
512
513
|
const menuElement = menu.menuElement;
|
|
513
|
-
menuElement.
|
|
514
|
+
menuElement.remove();
|
|
514
515
|
}
|
|
515
516
|
this._itemsCfg = [];
|
|
516
517
|
this._rootMenu = null;
|
|
@@ -738,21 +739,22 @@ class ContextMenu {
|
|
|
738
739
|
|
|
739
740
|
const itemRect = itemElement.getBoundingClientRect();
|
|
740
741
|
const menuRect = subMenuElement.getBoundingClientRect();
|
|
742
|
+
const offsetRect = self._offsetParent.getBoundingClientRect();
|
|
741
743
|
|
|
742
744
|
const subMenuWidth = 200; // TODO
|
|
743
|
-
const showOnRight = (itemRect.right + subMenuWidth) <
|
|
744
|
-
const showOnLeft = (itemRect.left - subMenuWidth) >
|
|
745
|
-
|
|
745
|
+
const showOnRight = (itemRect.right + subMenuWidth) < offsetRect.right;
|
|
746
|
+
const showOnLeft = (itemRect.left - subMenuWidth) > offsetRect.left;
|
|
747
|
+
|
|
746
748
|
if(showOnRight)
|
|
747
|
-
self._showMenu(subMenu.id, itemRect.right - 5, itemRect.top - 1);
|
|
749
|
+
self._showMenu(subMenu.id, itemRect.right + window.scrollX - 5, itemRect.top + window.scrollY - 1);
|
|
748
750
|
else if (showOnLeft)
|
|
749
|
-
self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);
|
|
751
|
+
self._showMenu(subMenu.id, itemRect.left - subMenuWidth + window.scrollX, itemRect.top + window.scrollY - 1);
|
|
750
752
|
else {
|
|
751
|
-
const spaceOnLeft = itemRect.left, spaceOnRight =
|
|
753
|
+
const spaceOnLeft = itemRect.left - offsetRect.left, spaceOnRight = offsetRect.right - itemRect.right;
|
|
752
754
|
if(spaceOnRight > spaceOnLeft)
|
|
753
|
-
self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top - 1);
|
|
755
|
+
self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top + window.scrollY - 1);
|
|
754
756
|
else
|
|
755
|
-
self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top - 1);
|
|
757
|
+
self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top + window.scrollY - 1);
|
|
756
758
|
}
|
|
757
759
|
|
|
758
760
|
lastSubMenu = subMenu;
|
|
@@ -945,14 +947,21 @@ class ContextMenu {
|
|
|
945
947
|
menuElement.style.display = 'block';
|
|
946
948
|
const menuHeight = menuElement.offsetHeight;
|
|
947
949
|
const menuWidth = menuElement.offsetWidth;
|
|
948
|
-
|
|
949
|
-
|
|
950
|
+
|
|
951
|
+
const offsetRect = this._offsetParent.getBoundingClientRect();
|
|
952
|
+
|
|
953
|
+
const bottomContainerBorder = offsetRect.bottom + window.scrollY;
|
|
954
|
+
const rightContainerBorder = offsetRect.right + window.scrollX;
|
|
955
|
+
if ((pageY + menuHeight) > bottomContainerBorder) {
|
|
956
|
+
pageY = bottomContainerBorder- menuHeight;
|
|
950
957
|
}
|
|
951
|
-
if ((pageX + menuWidth) >
|
|
952
|
-
pageX =
|
|
958
|
+
if ((pageX + menuWidth) > rightContainerBorder) {
|
|
959
|
+
pageX = rightContainerBorder - menuWidth;
|
|
953
960
|
}
|
|
954
|
-
|
|
955
|
-
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
menuElement.style.left = pageX - offsetRect.left - window.scrollX + 'px';
|
|
964
|
+
menuElement.style.top = pageY - offsetRect.top - window.scrollY + 'px';
|
|
956
965
|
}
|
|
957
966
|
|
|
958
967
|
_hideMenuElement(menuElement) {
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClampToEdgeWrapping,
|
|
3
|
+
LinearEncoding,
|
|
4
|
+
Mesh,
|
|
5
|
+
PhongMaterial,
|
|
6
|
+
ReadableGeometry,
|
|
7
|
+
Texture
|
|
8
|
+
} from "../../viewer/index.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {Component} scene
|
|
12
|
+
* @param {*} [cfg] Texture configuration
|
|
13
|
+
* @param {String[]} [cfg.src=null] Path to 6 images
|
|
14
|
+
* @param {Number} [cfg.encoding=LinearEncoding] Texture encoding format. See the {@link Texture#encoding} property for more info.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export async function createCombinedTexture(scene, cfg) {
|
|
18
|
+
if(!cfg.src || !Array.isArray(cfg.src) || cfg.src.length !== 6)
|
|
19
|
+
throw new Error("src requires path to 6 images");
|
|
20
|
+
const [
|
|
21
|
+
posX,
|
|
22
|
+
negX,
|
|
23
|
+
posY,
|
|
24
|
+
negY,
|
|
25
|
+
posZ,
|
|
26
|
+
negZ
|
|
27
|
+
] = cfg.src;
|
|
28
|
+
|
|
29
|
+
if (!posX || !negX || !posY || !negY || !posZ || !negZ) {
|
|
30
|
+
throw new Error("All six images must be provided");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const canvas = document.createElement('canvas');
|
|
34
|
+
const ctx = canvas.getContext('2d');
|
|
35
|
+
|
|
36
|
+
const loadImage = src => {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
const img = new Image();
|
|
39
|
+
img.crossOrigin = "anonymous";
|
|
40
|
+
img.onload = () => resolve(img);
|
|
41
|
+
img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
|
|
42
|
+
img.src = src;
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const [imgPosX, imgNegX, imgPosY, imgNegY, imgPosZ, imgNegZ] = await Promise.all([
|
|
48
|
+
loadImage(posX),
|
|
49
|
+
loadImage(negX),
|
|
50
|
+
loadImage(posY),
|
|
51
|
+
loadImage(negY),
|
|
52
|
+
loadImage(posZ),
|
|
53
|
+
loadImage(negZ)
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
const imageSize = imgPosX.width;
|
|
57
|
+
if (
|
|
58
|
+
imgNegX.width !== imageSize || imgPosY.width !== imageSize ||
|
|
59
|
+
imgNegY.width !== imageSize || imgPosZ.width !== imageSize ||
|
|
60
|
+
imgNegZ.width !== imageSize
|
|
61
|
+
) {
|
|
62
|
+
throw new Error("All skybox textures must have the same dimensions");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Set canvas size for the Christ cross layout (3×4 grid)
|
|
66
|
+
canvas.width = imageSize * 4;
|
|
67
|
+
canvas.height = imageSize * 3;
|
|
68
|
+
|
|
69
|
+
ctx.fillStyle = 'black';
|
|
70
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
71
|
+
|
|
72
|
+
ctx.drawImage(imgNegX, imageSize * 0, imageSize * 1, imageSize, imageSize); // -X (left)
|
|
73
|
+
ctx.drawImage(imgPosX, imageSize * 2, imageSize * 1, imageSize, imageSize); // +X (right)
|
|
74
|
+
ctx.drawImage(imgPosY, imageSize * 1, imageSize * 0, imageSize, imageSize); // +Y (top)
|
|
75
|
+
ctx.drawImage(imgNegY, imageSize * 1, imageSize * 2, imageSize, imageSize); // -Y (bottom)
|
|
76
|
+
ctx.drawImage(imgPosZ, imageSize * 1, imageSize * 1, imageSize, imageSize); // +Z (front)
|
|
77
|
+
ctx.drawImage(imgNegZ, imageSize * 3, imageSize * 1, imageSize, imageSize); // -Z (back)
|
|
78
|
+
|
|
79
|
+
const combinedTexture = new Texture(scene, {
|
|
80
|
+
image: canvas,
|
|
81
|
+
flipY: true,
|
|
82
|
+
wrapS: ClampToEdgeWrapping,
|
|
83
|
+
wrapT: ClampToEdgeWrapping,
|
|
84
|
+
encoding: cfg.encoding || LinearEncoding
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return combinedTexture;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error("Error creating combined skybox texture:", error);
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @param {Component} scene
|
|
96
|
+
* @param {Texture} [texture] Texture to be used on the skybox mesh
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
export function createSkyboxMesh(scene, texture) {
|
|
100
|
+
|
|
101
|
+
return new Mesh(scene, {
|
|
102
|
+
|
|
103
|
+
geometry: new ReadableGeometry(scene, { // Box-shaped geometry
|
|
104
|
+
primitive: "triangles",
|
|
105
|
+
positions: [
|
|
106
|
+
1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front
|
|
107
|
+
1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v5 right
|
|
108
|
+
1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v5-v6-v1 top
|
|
109
|
+
-1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left
|
|
110
|
+
-1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, // v7-v4-v3-v2 bottom
|
|
111
|
+
1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v5 back
|
|
112
|
+
],
|
|
113
|
+
uv: [
|
|
114
|
+
0.5, 0.6666, 0.25, 0.6666, 0.25, 0.3333, 0.5, 0.3333, 0.5, 0.6666, 0.5, 0.3333, 0.75, 0.3333, 0.75, 0.6666,
|
|
115
|
+
0.5, 0.6666, 0.5, 1, 0.25, 1, 0.25, 0.6666, 0.25, 0.6666, 0.0, 0.6666, 0.0, 0.3333, 0.25, 0.3333,
|
|
116
|
+
0.25, 0, 0.50, 0, 0.50, 0.3333, 0.25, 0.3333, 0.75, 0.3333, 1.0, 0.3333, 1.0, 0.6666, 0.75, 0.6666
|
|
117
|
+
],
|
|
118
|
+
indices: [
|
|
119
|
+
0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11,
|
|
120
|
+
12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23
|
|
121
|
+
]
|
|
122
|
+
}),
|
|
123
|
+
background: true,
|
|
124
|
+
scale: [1000, 1000, 1000],
|
|
125
|
+
rotation: [0, -90, 0],
|
|
126
|
+
material: new PhongMaterial(scene, {
|
|
127
|
+
ambient: [0, 0, 0],
|
|
128
|
+
diffuse: [0, 0, 0],
|
|
129
|
+
specular: [0, 0, 0],
|
|
130
|
+
emissive: [1, 1, 1],
|
|
131
|
+
emissiveMap: texture,
|
|
132
|
+
backfaces: true // Show interior faces of our skybox geometry
|
|
133
|
+
}),
|
|
134
|
+
visible: true,
|
|
135
|
+
pickable: false,
|
|
136
|
+
clippable: false,
|
|
137
|
+
collidable: false
|
|
138
|
+
});
|
|
139
|
+
}
|
package/src/extras/index.js
CHANGED
|
@@ -2,4 +2,5 @@ export * from "./ContextMenu/index.js";
|
|
|
2
2
|
export * from "./PointerLens/index.js";
|
|
3
3
|
export * from "./collision/index.js";
|
|
4
4
|
export * from "./MarqueePicker/index.js";
|
|
5
|
-
export * from "./PointerCircle/index.js";
|
|
5
|
+
export * from "./PointerCircle/index.js";
|
|
6
|
+
export * from "./Skybox/index.js";
|
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
import { Plugin } from "../../viewer/Plugin.js";
|
|
2
|
-
import { GLTFLoaderPlugin } from "../GLTFLoaderPlugin/GLTFLoaderPlugin.js";
|
|
3
|
-
import { ifc2gltf } from "@creooxag/cx-converter";
|
|
1
|
+
// import { Plugin } from "../../viewer/Plugin.js";
|
|
2
|
+
// import { GLTFLoaderPlugin } from "../GLTFLoaderPlugin/GLTFLoaderPlugin.js";
|
|
3
|
+
// import { ifc2gltf } from "@creooxag/cx-converter";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
async function fetchFile(url) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
5
|
+
// /**
|
|
6
|
+
// * Fetches a file from the given URL and returns its contents as text.
|
|
7
|
+
// *
|
|
8
|
+
// * @param {string} url - The URL to fetch the file from.
|
|
9
|
+
// * @returns {Promise<string>} A promise that resolves to the file contents.
|
|
10
|
+
// * @private
|
|
11
|
+
// */
|
|
12
|
+
// async function fetchFile(url) {
|
|
13
|
+
// try {
|
|
14
|
+
// const response = await fetch(url);
|
|
15
|
+
// if (!response.ok) {
|
|
16
|
+
// throw new Error(`HTTP error! Status: ${response.status}`);
|
|
17
|
+
// }
|
|
18
|
+
// return response.text();
|
|
19
|
+
// } catch (error) {
|
|
20
|
+
// console.error('Error fetching file:', error);
|
|
21
|
+
// }
|
|
22
|
+
// }
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
// /**
|
|
25
|
+
// * {@link Viewer} plugin that uses [CxConverter](https://github.com/Creoox/cxconverter) to load BIM models directly from IFC files, using its WebAssembly buid from [npm package](https://www.npmjs.com/package/@creooxag/cx-converter).
|
|
26
|
+
// *
|
|
27
|
+
// * ## Overview
|
|
28
|
+
// * The WebAssembly build of CxConverter is still in alfa stage, so it may not work as expected. This documentation will be updated as the library and the plugin evolve. The example below shows how to use the plugin:
|
|
29
|
+
// * ````javascript
|
|
30
|
+
// * import { CxConverterIFCLoaderPlugin, Viewer } from "../../dist/xeokit-sdk.es.js";
|
|
31
|
+
// * const cxConverterIFCLoaderPlugin = new CxConverterIFCLoaderPlugin(viewer);
|
|
32
|
+
// *
|
|
33
|
+
// * const sceneModel = await cxConverterIFCLoaderPlugin.load({
|
|
34
|
+
// * src: "../../assets/models/ifc/Duplex.ifc"
|
|
35
|
+
// * });
|
|
36
|
+
// * ````
|
|
37
|
+
// See the code in action [here](https://xeokit.github.io/xeokit-sdk/examples/buildings/#cxConverterIFC_vbo_Duplex).
|
|
38
|
+
// */
|
|
39
39
|
|
|
40
|
-
class CxConverterIFCLoaderPlugin extends Plugin {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
// class CxConverterIFCLoaderPlugin extends Plugin {
|
|
41
|
+
// /**
|
|
42
|
+
// * @constructor
|
|
43
|
+
// * @param {Viewer} viewer The Viewer.
|
|
44
|
+
// * @param {Object} [cfg={}] Plugin configuration.
|
|
45
|
+
// */
|
|
46
|
+
// constructor(viewer, cfg = {}) {
|
|
47
|
+
// super("ifcLoader", viewer, cfg);
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
// /**
|
|
50
|
+
// * The GLTFLoaderPlugin used internally to load the converted GLTF.
|
|
51
|
+
// * @type {GLTFLoaderPlugin}
|
|
52
|
+
// */
|
|
53
|
+
// this.gltfLoader = new GLTFLoaderPlugin(this.viewer);
|
|
54
|
+
// }
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
export { CxConverterIFCLoaderPlugin };
|
|
56
|
+
// /**
|
|
57
|
+
// * Loads an IFC model from the given source.
|
|
58
|
+
// *
|
|
59
|
+
// * @param {Object} [params={}] Loading parameters.
|
|
60
|
+
// * @param {string} params.src Path to an IFC file.
|
|
61
|
+
// * @param {Function} [params.progressCallback] Callback to track loading progress.
|
|
62
|
+
// * @param {Function} [params.progressTextCallback] Callback to track loading progress with text updates.
|
|
63
|
+
// * @returns {Promise<SceneModel>} A promise that resolves to the loaded SceneModel.
|
|
64
|
+
// */
|
|
65
|
+
// async load(params = {}) {
|
|
66
|
+
// if (!params.src) {
|
|
67
|
+
// this.error("load() param expected: src");
|
|
68
|
+
// }
|
|
69
|
+
// const data = await fetchFile(params.src);
|
|
70
|
+
// const { gltf, metaData } = await ifc2gltf(
|
|
71
|
+
// data,
|
|
72
|
+
// {
|
|
73
|
+
// remote: true,
|
|
74
|
+
// progressCallback: params.progressCallback,
|
|
75
|
+
// progressTextCallback: params.progressTextCallback
|
|
76
|
+
// }
|
|
77
|
+
// );
|
|
78
|
+
// const sceneModel = this.gltfLoader.load({
|
|
79
|
+
// id: "myModel",
|
|
80
|
+
// gltf: gltf,
|
|
81
|
+
// metaModelJSON: metaData
|
|
82
|
+
// });
|
|
83
|
+
// return sceneModel;
|
|
84
|
+
// }
|
|
85
|
+
// }
|
|
86
|
+
// export { CxConverterIFCLoaderPlugin };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./CxConverterIFCLoaderPlugin.js";
|
|
1
|
+
// export * from "./CxConverterIFCLoaderPlugin.js";
|
|
@@ -108,6 +108,7 @@ class FastNavPlugin extends Plugin {
|
|
|
108
108
|
* @param {Number} [cfg.scaleCanvasResolutionFactor=0.6] The factor by which we downscale the canvas resolution whenever we interact with the Viewer.
|
|
109
109
|
* @param {Boolean} [cfg.delayBeforeRestore=true] Whether to temporarily have a delay before restoring normal rendering after we stop interacting with the Viewer.
|
|
110
110
|
* @param {Number} [cfg.delayBeforeRestoreSeconds=0.5] Delay in seconds before restoring normal rendering after we stop interacting with the Viewer.
|
|
111
|
+
* @param {Function} [cfg.onMoved] Optional callback function fired during moving mode, should return the callback function that will be fired when the interaction stops.
|
|
111
112
|
*/
|
|
112
113
|
constructor(viewer, cfg = {}) {
|
|
113
114
|
|
|
@@ -123,6 +124,8 @@ class FastNavPlugin extends Plugin {
|
|
|
123
124
|
this._scaleCanvasResolutionFactor = cfg.scaleCanvasResolutionFactor || 0.6;
|
|
124
125
|
this._delayBeforeRestore = (cfg.delayBeforeRestore !== false);
|
|
125
126
|
this._delayBeforeRestoreSeconds = cfg.delayBeforeRestoreSeconds || 0.5;
|
|
127
|
+
this._onMoved = cfg.onMoved;
|
|
128
|
+
this._onStopped = null;
|
|
126
129
|
|
|
127
130
|
let timer = this._delayBeforeRestoreSeconds * 1000;
|
|
128
131
|
let fastMode = false;
|
|
@@ -141,6 +144,10 @@ class FastNavPlugin extends Plugin {
|
|
|
141
144
|
} else {
|
|
142
145
|
viewer.scene.canvas.resolutionScale = this._defaultScaleCanvasResolutionFactor;
|
|
143
146
|
}
|
|
147
|
+
if (this._onMoved) {
|
|
148
|
+
this._onStopped = this._onMoved();
|
|
149
|
+
}
|
|
150
|
+
|
|
144
151
|
fastMode = true;
|
|
145
152
|
}
|
|
146
153
|
};
|
|
@@ -152,10 +159,12 @@ class FastNavPlugin extends Plugin {
|
|
|
152
159
|
viewer.scene._renderer.setPBREnabled(true);
|
|
153
160
|
viewer.scene._renderer.setSAOEnabled(true);
|
|
154
161
|
viewer.scene._renderer.setTransparentEnabled(true);
|
|
162
|
+
if (this._onStopped) {
|
|
163
|
+
this._onStopped();
|
|
164
|
+
}
|
|
155
165
|
fastMode = false;
|
|
156
166
|
};
|
|
157
167
|
|
|
158
|
-
this._onCanvasBoundary = viewer.scene.canvas.on("boundary", switchToLowQuality);
|
|
159
168
|
this._onCameraMatrix = viewer.scene.camera.on("matrix", switchToLowQuality);
|
|
160
169
|
|
|
161
170
|
this._onSceneTick = viewer.scene.on("tick", (tickEvent) => {
|
|
@@ -167,23 +176,6 @@ class FastNavPlugin extends Plugin {
|
|
|
167
176
|
switchToHighQuality();
|
|
168
177
|
}
|
|
169
178
|
});
|
|
170
|
-
|
|
171
|
-
let down = false;
|
|
172
|
-
|
|
173
|
-
this._onSceneMouseDown = viewer.scene.input.on("mousedown", () => {
|
|
174
|
-
down = true;
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
this._onSceneMouseUp = viewer.scene.input.on("mouseup", () => {
|
|
178
|
-
down = false;
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
this._onSceneMouseMove = viewer.scene.input.on("mousemove", () => {
|
|
182
|
-
if (!down) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
switchToLowQuality();
|
|
186
|
-
});
|
|
187
179
|
}
|
|
188
180
|
|
|
189
181
|
/**
|
|
@@ -460,7 +460,7 @@ class Control {
|
|
|
460
460
|
|
|
461
461
|
{ // Keep gizmo screen size constant
|
|
462
462
|
let lastDist = -1;
|
|
463
|
-
const setRootNodeScale = size => rootNode.scale = [size, size, size];
|
|
463
|
+
const setRootNodeScale = size => { if (size !== rootNode.scale[0]) { rootNode.scale = [size, size, size]; } };
|
|
464
464
|
const onSceneTick = scene.on("tick", () => {
|
|
465
465
|
const dist = Math.abs(math.distVec3(camera.eye, pos));
|
|
466
466
|
if (camera.projection === "perspective") {
|
|
@@ -5,6 +5,15 @@ import { addContextMenuListener } from "../lib/html/MenuEvent.js";
|
|
|
5
5
|
*/
|
|
6
6
|
export class RenderService {
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @constructor
|
|
10
|
+
*
|
|
11
|
+
* @param {HTMLElement} treeViewContainer Container element for the tree which uses this render service.
|
|
12
|
+
*/
|
|
13
|
+
constructor(treeViewContainer) {
|
|
14
|
+
this._treeViewContainer = treeViewContainer;
|
|
15
|
+
}
|
|
16
|
+
|
|
8
17
|
/*
|
|
9
18
|
* Creates the root node of the tree.
|
|
10
19
|
* @return {HTMLElement} The root node of the tree.
|
|
@@ -129,7 +138,7 @@ export class RenderService {
|
|
|
129
138
|
}
|
|
130
139
|
|
|
131
140
|
getSwitchElement(nodeId) {
|
|
132
|
-
return
|
|
141
|
+
return this._treeViewContainer.querySelector(`[id="switch-${nodeId}"]`);
|
|
133
142
|
}
|
|
134
143
|
|
|
135
144
|
isChecked(element) {
|
|
@@ -137,7 +146,7 @@ export class RenderService {
|
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
setCheckbox(nodeId, checked, indeterminate = false) {
|
|
140
|
-
const checkbox =
|
|
149
|
+
const checkbox = this._treeViewContainer.querySelector(`[id="checkbox-${nodeId}"]`);
|
|
141
150
|
if (checkbox) {
|
|
142
151
|
if (checked !== checkbox.checked) {
|
|
143
152
|
checkbox.checked = checked;
|
|
@@ -152,7 +161,7 @@ export class RenderService {
|
|
|
152
161
|
}
|
|
153
162
|
|
|
154
163
|
setXRayed(nodeId, xrayed) {
|
|
155
|
-
const treeNode =
|
|
164
|
+
const treeNode = this._treeViewContainer.querySelector(`[id="${nodeId}"]`);
|
|
156
165
|
if (treeNode) {
|
|
157
166
|
if (xrayed) {
|
|
158
167
|
treeNode.classList.add('xrayed-node');
|
|
@@ -163,7 +172,7 @@ export class RenderService {
|
|
|
163
172
|
}
|
|
164
173
|
|
|
165
174
|
setHighlighted(nodeId, highlighted) {
|
|
166
|
-
const treeNode =
|
|
175
|
+
const treeNode = this._treeViewContainer.querySelector(`[id="${nodeId}"]`);
|
|
167
176
|
if (treeNode) {
|
|
168
177
|
if (highlighted) {
|
|
169
178
|
treeNode.scrollIntoView({block: "center"});
|
|
@@ -415,7 +415,7 @@ export class TreeViewPlugin extends Plugin {
|
|
|
415
415
|
this._sortNodes = cfg.sortNodes;
|
|
416
416
|
this._pruneEmptyNodes = cfg.pruneEmptyNodes;
|
|
417
417
|
this._showListItemElementId = null;
|
|
418
|
-
this._renderService = cfg.renderService || new RenderService();
|
|
418
|
+
this._renderService = cfg.renderService || new RenderService(this._containerElement);
|
|
419
419
|
this._showIndeterminate = cfg.showIndeterminate ?? false;
|
|
420
420
|
this._showProjectNode = cfg.showProjectNode ?? false;
|
|
421
421
|
this._elevationSortFunction = cfg.elevationSortFunction ?? undefined;
|
package/src/plugins/index.js
CHANGED
|
@@ -10,7 +10,6 @@ export * from "./OBJLoaderPlugin/index.js";
|
|
|
10
10
|
export * from "./SectionPlanesPlugin/index.js";
|
|
11
11
|
export * from "./StoreyViewsPlugin/index.js";
|
|
12
12
|
export * from "./FaceAlignedSectionPlanesPlugin/index.js";
|
|
13
|
-
export * from "./SkyboxesPlugin/index.js";
|
|
14
13
|
export * from "./STLLoaderPlugin/index.js";
|
|
15
14
|
export * from "./TreeViewPlugin/index.js";
|
|
16
15
|
export * from "./ViewCullPlugin/index.js";
|
package/src/viewer/Viewer.js
CHANGED
|
@@ -363,22 +363,6 @@ class Viewer {
|
|
|
363
363
|
this.sendToPlugins("snapshotStarting"); // Tells plugins to hide things that shouldn't be in snapshot
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
const captured = {};
|
|
367
|
-
for (let i = 0, len = this._plugins.length; i < len; i++) {
|
|
368
|
-
const plugin = this._plugins[i];
|
|
369
|
-
if (plugin.getContainerElement) {
|
|
370
|
-
const container = plugin.getContainerElement();
|
|
371
|
-
if (container !== document.body) {
|
|
372
|
-
if (!captured[container.id]) {
|
|
373
|
-
captured[container.id] = true;
|
|
374
|
-
html2canvas(container).then(function (canvas) {
|
|
375
|
-
document.body.appendChild(canvas);
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
366
|
// firing "rendering" is necessary to trigger DTX{Lines,Triangles}Layer::_uploadDeferredFlags
|
|
383
367
|
this.scene.fire("rendering", { }, true);
|
|
384
368
|
|
|
@@ -13,6 +13,9 @@ const tempVec4a = math.vec4();
|
|
|
13
13
|
const tempVec4b = math.vec4();
|
|
14
14
|
const tempVec4c = math.vec4();
|
|
15
15
|
|
|
16
|
+
const TOP_LIMIT = 0.001;
|
|
17
|
+
const BOTTOM_LIMIT = Math.PI - 0.001;
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
/** @private */
|
|
18
21
|
class PivotController {
|
|
@@ -188,14 +191,9 @@ class PivotController {
|
|
|
188
191
|
*/
|
|
189
192
|
startPivot() {
|
|
190
193
|
|
|
191
|
-
if (this._cameraLookingDownwards()) {
|
|
192
|
-
this._pivoting = false;
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
194
|
const camera = this._scene.camera;
|
|
197
195
|
|
|
198
|
-
let lookat = math.lookAtMat4v(camera.eye, camera.look, camera.
|
|
196
|
+
let lookat = math.lookAtMat4v(camera.eye, camera.look, camera.up);
|
|
199
197
|
math.transformPoint3(lookat, this.getPivotPos(), this._cameraOffset);
|
|
200
198
|
|
|
201
199
|
const pivotPos = this.getPivotPos();
|
|
@@ -298,8 +296,31 @@ class PivotController {
|
|
|
298
296
|
dx = -dx;
|
|
299
297
|
}
|
|
300
298
|
this._azimuth += -dx * .01;
|
|
301
|
-
|
|
302
|
-
|
|
299
|
+
|
|
300
|
+
const isMovingUp = dy < 0;
|
|
301
|
+
const isMovingDown = dy > 0;
|
|
302
|
+
|
|
303
|
+
// Track if we're at limits - only check if we're very close to the limit
|
|
304
|
+
const atTopLimit = Math.abs(this._polar - TOP_LIMIT) < 0.005;
|
|
305
|
+
const atBottomLimit = Math.abs(this._polar - BOTTOM_LIMIT) < 0.005;
|
|
306
|
+
|
|
307
|
+
let newPolar = this._polar + dy * .01;
|
|
308
|
+
|
|
309
|
+
// Case 1: At top limit and trying to go beyond
|
|
310
|
+
if (atTopLimit && isMovingUp) {
|
|
311
|
+
newPolar = TOP_LIMIT;
|
|
312
|
+
}
|
|
313
|
+
// Case 2: At bottom limit and trying to go beyond
|
|
314
|
+
else if (atBottomLimit && isMovingDown) {
|
|
315
|
+
newPolar = BOTTOM_LIMIT;
|
|
316
|
+
}
|
|
317
|
+
// Case 3: Normal rotation or moving away from a limit
|
|
318
|
+
else {
|
|
319
|
+
newPolar = math.clamp(newPolar, TOP_LIMIT, BOTTOM_LIMIT);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
this._polar = newPolar;
|
|
323
|
+
|
|
303
324
|
const pos = [
|
|
304
325
|
this._radius * Math.sin(this._polar) * Math.sin(this._azimuth),
|
|
305
326
|
this._radius * Math.cos(this._polar),
|