@xeokit/xeokit-sdk 2.6.95 → 2.6.97

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.
@@ -17,6 +17,9 @@ const vec3_0 = math.vec3([0,0,0]);
17
17
 
18
18
  const iota = (n) => { const ret = [ ]; for (let i = 0; i < n; ++i) ret.push(i); return ret; };
19
19
 
20
+ const tempPlanes = iota(6).map(() => math.vec4());
21
+ const tempVec4 = math.vec4();
22
+
20
23
  const bitShiftScreenZ = math.vec4([1.0 / (256.0 * 256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0]);
21
24
 
22
25
  const pixelToInt = pix => pix[0] + (pix[1] << 8) + (pix[2] << 16) + (pix[3] << 24);
@@ -26,6 +29,66 @@ const toWorldPos = (p, origin, scale) => math.vec3([ p[0] * scale[0] + origin
26
29
  p[1] * scale[1] + origin[1],
27
30
  p[2] * scale[2] + origin[2] ]);
28
31
 
32
+ const makeFrustumAABBIntersectionTest = function(camera) {
33
+ const m = math.mat4();
34
+ math.mulMat4(camera.projMatrix, camera.viewMatrix, m);
35
+
36
+ for (let i = 0; i < 3; ++i) {
37
+ tempPlanes[i * 2 + 0][0] = m[ 3] + m[i];
38
+ tempPlanes[i * 2 + 0][1] = m[ 7] + m[i + 4];
39
+ tempPlanes[i * 2 + 0][2] = m[11] + m[i + 8];
40
+ tempPlanes[i * 2 + 0][3] = m[15] + m[i + 12];
41
+
42
+ tempPlanes[i * 2 + 1][0] = m[ 3] - m[i];
43
+ tempPlanes[i * 2 + 1][1] = m[ 7] - m[i + 4];
44
+ tempPlanes[i * 2 + 1][2] = m[11] - m[i + 8];
45
+ tempPlanes[i * 2 + 1][3] = m[15] - m[i + 12];
46
+ }
47
+
48
+ // Normalize each plane
49
+ tempPlanes.forEach(p => math.divVec4Scalar(p, math.lenVec3(p), p));
50
+
51
+ return aabb => tempPlanes.every(p => {
52
+ // Compute the positive vertex (farthest in direction of normal)
53
+ tempVec4[0] = aabb[(p[0] >= 0) ? 3 : 0];
54
+ tempVec4[1] = aabb[(p[1] >= 0) ? 4 : 1];
55
+ tempVec4[2] = aabb[(p[2] >= 0) ? 5 : 2];
56
+ tempVec4[3] = 1;
57
+ return math.dotVec4(p, tempVec4) >= 0;
58
+ });
59
+ };
60
+
61
+ const makeRayAABBIntersectionTest = (O, D) => aabb => {
62
+ let tmin = -Infinity;
63
+ let tmax = Infinity;
64
+
65
+ for (let i = 0; i < 3; i++) {
66
+ const origin = O[i];
67
+ const direction = D[i];
68
+ const minBound = aabb[i];
69
+ const maxBound = aabb[i + 3];
70
+
71
+ if (Math.abs(direction) < 1e-8) {
72
+ // Ray is parallel to plane
73
+ if ((origin < minBound) || (origin > maxBound)) {
74
+ return false; // No intersection
75
+ }
76
+ } else {
77
+ const t1 = (minBound - origin) / direction;
78
+ const t2 = (maxBound - origin) / direction;
79
+
80
+ tmin = Math.max(tmin, Math.min(t1, t2)); // near
81
+ tmax = Math.min(tmax, Math.max(t1, t2)); // far
82
+
83
+ if (tmin > tmax) {
84
+ return false; // No intersection
85
+ }
86
+ }
87
+ }
88
+
89
+ return tmax >= 0; // Check if intersection is in front of ray
90
+ };
91
+
29
92
  /**
30
93
  * @private
31
94
  */
@@ -789,6 +852,8 @@ const Renderer = function (scene, options) {
789
852
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
790
853
  }
791
854
 
855
+ frameCtx.testAABB = makeFrustumAABBIntersectionTest(scene.camera);
856
+
792
857
  const renderDrawables = function(drawables) {
793
858
 
794
859
  let normalDrawSAOBinLen = 0;
@@ -1123,6 +1188,8 @@ const Renderer = function (scene, options) {
1123
1188
  renderDrawables(uiDrawableList);
1124
1189
  }
1125
1190
 
1191
+ frameCtx.testAABB = null;
1192
+
1126
1193
  const endTime = Date.now();
1127
1194
  const frameStats = stats.frame;
1128
1195
 
@@ -1231,11 +1298,16 @@ const Renderer = function (scene, options) {
1231
1298
 
1232
1299
  pickResult.canvasPos = params.canvasPos;
1233
1300
 
1301
+ math.canvasPosToWorldRay(canvas, pickViewMatrix, pickProjMatrix, projection, canvasPos, tempVec3a, tempVec3b);
1302
+ frameCtx.testAABB = makeRayAABBIntersectionTest(tempVec3a, tempVec3b);
1234
1303
  } else {
1235
1304
 
1236
1305
  // Picking with arbitrary World-space ray
1237
1306
  // Align camera along ray and fire ray through center of canvas
1238
1307
 
1308
+ canvasPos[0] = canvas.clientWidth * 0.5;
1309
+ canvasPos[1] = canvas.clientHeight * 0.5;
1310
+
1239
1311
  if (params.matrix) {
1240
1312
 
1241
1313
  pickViewMatrix = params.matrix;
@@ -1245,6 +1317,8 @@ const Renderer = function (scene, options) {
1245
1317
  nearAndFar[0] = camera.project.near;
1246
1318
  nearAndFar[1] = camera.project.far;
1247
1319
 
1320
+ math.canvasPosToWorldRay(canvas, pickViewMatrix, pickProjMatrix, projection, canvasPos, tempVec3a, tempVec3b);
1321
+ frameCtx.testAABB = makeRayAABBIntersectionTest(tempVec3a, tempVec3b);
1248
1322
  } else {
1249
1323
 
1250
1324
  worldRayOrigin.set(params.origin || [0, 0, 0]);
@@ -1273,10 +1347,9 @@ const Renderer = function (scene, options) {
1273
1347
 
1274
1348
  pickResult.origin = worldRayOrigin;
1275
1349
  pickResult.direction = worldRayDir;
1276
- }
1277
1350
 
1278
- canvasPos[0] = canvas.clientWidth * 0.5;
1279
- canvasPos[1] = canvas.clientHeight * 0.5;
1351
+ frameCtx.testAABB = makeRayAABBIntersectionTest(pickResult.origin, pickResult.direction);
1352
+ }
1280
1353
  }
1281
1354
 
1282
1355
  pickBuffer.bind();
@@ -1313,6 +1386,8 @@ const Renderer = function (scene, options) {
1313
1386
  renderDrawables(uiDrawableList);
1314
1387
  }
1315
1388
 
1389
+ frameCtx.testAABB = null;
1390
+
1316
1391
  const pickID = pixelToInt(pickBuffer.read(0, 0));
1317
1392
  const pickable = (pickID >= 0) && pickIDs.items[pickID];
1318
1393
 
@@ -1844,4 +1919,4 @@ const Renderer = function (scene, options) {
1844
1919
  };
1845
1920
  };
1846
1921
 
1847
- export {Renderer};
1922
+ export {Renderer};
@@ -0,0 +1,107 @@
1
+ import { Plugin, Viewer, SceneModel } from "../../viewer";
2
+ import { ModelStats } from "../index";
3
+
4
+ /**
5
+ * Default data source for loading IFC files in IFCOpenShellLoaderPlugin.
6
+ * Loads files via HTTP by default.
7
+ */
8
+ export declare interface IFCOpenShellDefaultDataSource {
9
+ /**
10
+ * Loads the contents of the given IFC file as an ArrayBuffer.
11
+ * @param src Path or ID of the IFC file.
12
+ * @param ok Callback on success, receives the IFC file as an ArrayBuffer.
13
+ * @param error Callback on error, receives an Error.
14
+ */
15
+ getIFC(src: string | number, ok: (buffer: ArrayBuffer) => void, error: (e: Error) => void): void;
16
+
17
+ /** Whether to append a cache-busting query parameter to requests. */
18
+ get cacheBuster(): boolean;
19
+ set cacheBuster(value: boolean);
20
+ }
21
+
22
+ /**
23
+ * Configuration options for IFCOpenShellLoaderPlugin.
24
+ */
25
+ export declare type IFCOpenShellLoaderPluginConfigs = {
26
+ /** Optional plugin ID. */
27
+ id?: string;
28
+ /** Custom data source for loading IFC files. */
29
+ dataSource?: IFCOpenShellDefaultDataSource;
30
+ /** Pyodide proxy for the ifcopenshell module. */
31
+ ifcopenshell: any;
32
+ /** Pyodide proxy for the ifcopenshell.geom module. */
33
+ ifcopenshell_geom: any;
34
+ };
35
+
36
+ /**
37
+ * Parameters for loading an IFC model with IFCOpenShellLoaderPlugin.
38
+ */
39
+ export declare type LoadIFCOpenShellModel = {
40
+ /** Unique ID for the loaded SceneModel. */
41
+ id?: string;
42
+ /** Path to the IFC file. */
43
+ src?: string;
44
+ /** Whether to load IFC metadata (metaobject). */
45
+ loadMetadata?: boolean;
46
+ /** Whether to load IFC metadata property sets. Only works when `loadMetadata` is `true`. */
47
+ loadMetadataPropertySets?: boolean;
48
+ /** Exclude objects with types in this list. */
49
+ excludeTypes?: string[];
50
+ /** Render the model with edges emphasized. */
51
+ edges?: boolean;
52
+ /** World-space double-precision origin for the model. */
53
+ origin?: number[];
54
+ /** Single-precision position offset, relative to origin. */
55
+ position?: number[];
56
+ /** Model scale. */
57
+ scale?: number[];
58
+ /** Model orientation as Euler angles (degrees) for X, Y, Z. */
59
+ rotation?: number[];
60
+ /** Enable Scalable Ambient Obscurance (SAO) for the model. */
61
+ saoEnabled?: boolean;
62
+ /** Force rendering of backfaces for the model. */
63
+ backfaces?: boolean;
64
+ /** Globalize Entity and MetaObject IDs to avoid clashes. */
65
+ globalizeObjectIds?: boolean;
66
+ /** Collect model statistics. */
67
+ stats?: ModelStats;
68
+ /** Indicates if compact data texture scene representation is enabled for this model. */
69
+ dtxEnabled?: boolean;
70
+ };
71
+
72
+ /**
73
+ * Viewer plugin that uses IfcOpenShell to load BIM models directly from IFC files.
74
+ */
75
+ export declare class IFCOpenShellLoaderPlugin extends Plugin {
76
+ /**
77
+ * Creates a new IFCOpenShellLoaderPlugin.
78
+ * @param viewer The Viewer instance.
79
+ * @param cfg Plugin configuration.
80
+ */
81
+ constructor(viewer: Viewer, cfg?: IFCOpenShellLoaderPluginConfigs);
82
+
83
+ /**
84
+ * Sets a custom data source for loading IFC files.
85
+ * Default is IFCOpenShellDefaultDataSource, which loads via HTTP.
86
+ */
87
+ set dataSource(arg: IFCOpenShellDefaultDataSource);
88
+
89
+ /**
90
+ * Gets the current data source for loading IFC files.
91
+ * Default is IFCOpenShellDefaultDataSource, which loads via HTTP.
92
+ */
93
+ get dataSource(): IFCOpenShellDefaultDataSource;
94
+
95
+ /**
96
+ * Gets whether object and metaobject IDs are globalized to avoid clashes.
97
+ * Default is false.
98
+ */
99
+ get globalizeObjectIds(): boolean;
100
+
101
+ /**
102
+ * Loads an IFC model into the Viewer's scene.
103
+ * @param params Loading parameters.
104
+ * @returns SceneModel representing the loaded model.
105
+ */
106
+ load(params?: LoadIFCOpenShellModel): SceneModel;
107
+ }
@@ -0,0 +1 @@
1
+ export * from './IFCOpenShellLoaderPlugin';
@@ -8,6 +8,7 @@ export * from "./DistanceMeasurementsPlugin";
8
8
  export * from "./DotBIMLoaderPlugin";
9
9
  export * from "./FastNavPlugin";
10
10
  export * from "./GLTFLoaderPlugin";
11
+ export * from "./IFCOpenShellLoaderPlugin";
11
12
  export * from "./LASLoaderPlugin";
12
13
  export * from "./NavCubePlugin";
13
14
  export * from "./OBJLoaderPlugin";
@@ -170,20 +170,20 @@ export declare class CameraControl extends Component {
170
170
  *
171
171
  * See class docs for usage.
172
172
  *
173
- * @param {{Number:Number}|String} value Either a set of new key mappings, or a string to select a keyboard layout,
173
+ * @param {{Number:(Number | Number[])[]} | String} value Either a set of new key mappings, or a string to select a keyboard layout,
174
174
  * which causes ````CameraControl```` to use the default key mappings for that layout.
175
175
  */
176
176
  set keyMap(arg: {
177
- [key: number]: number;
178
- });
177
+ [key: number]: (number | number[])[];
178
+ } | string);
179
179
 
180
180
  /**
181
181
  * Gets custom mappings of keys to {@link CameraControl} actions.
182
182
  *
183
- * @returns {{Number:Number}} Current key mappings.
183
+ * @returns {{Number:(Number | Number[])[]}} Current key mappings.
184
184
  */
185
185
  get keyMap(): {
186
- [key: number]: number;
186
+ [key: number]: (number | number[])[];
187
187
  };
188
188
 
189
189
  /**