@xeokit/xeokit-sdk 2.6.58 → 2.6.60
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 +15 -6
- package/dist/xeokit-sdk.es.js +15 -6
- package/dist/xeokit-sdk.es5.js +72 -65
- package/dist/xeokit-sdk.min.cjs.js +5 -5
- package/dist/xeokit-sdk.min.es.js +5 -5
- package/dist/xeokit-sdk.min.es5.js +4 -4
- package/package.json +1 -1
- package/src/plugins/lib/ui/index.js +10 -0
- package/src/viewer/metadata/MetaModel.js +1 -1
- package/src/viewer/metadata/MetaScene.js +4 -5
- package/types/extras/MarqueePicker/MarqueePicker.d.ts +200 -0
- package/types/extras/MarqueePicker/MarqueePickerMouseControl.d.ts +48 -0
- package/types/extras/MarqueePicker/index.d.ts +2 -0
- package/types/extras/collision/ObjectsKdTree3.d.ts +43 -0
- package/types/extras/collision/index.d.ts +1 -0
- package/types/extras/index.d.ts +2 -0
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@ const tmpVec4a = math.vec4();
|
|
|
14
14
|
const tmpVec4b = math.vec4();
|
|
15
15
|
const tmpVec4c = math.vec4();
|
|
16
16
|
const tmpVec4d = math.vec4();
|
|
17
|
+
const tmpMat4 = math.mat4();
|
|
17
18
|
|
|
18
19
|
const nop = () => { };
|
|
19
20
|
|
|
@@ -25,6 +26,15 @@ export function transformToNode(from, to, vec) {
|
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
const toClipSpace = (camera, worldPos, p) => {
|
|
29
|
+
// The reason the projMatrix is explicitely fetched as below is a complex callback chain
|
|
30
|
+
// leading from a boundary update to a viewMatrix and projMatrix updates, which change their values
|
|
31
|
+
// in the mid of the toClipSpace, leading to incorrect values.
|
|
32
|
+
// The fetch ensures that matrix values are stabilized before used to transform worldPos to p.
|
|
33
|
+
// Better solution would be to ensure that no mutually-triggered callbacks
|
|
34
|
+
// (like boundary => view/projMatrix in this situation) ever happen, so user code can rely
|
|
35
|
+
// on a callback running in a stable context.
|
|
36
|
+
tmpMat4.set(camera.viewMatrix);
|
|
37
|
+
tmpMat4.set(camera.projMatrix);
|
|
28
38
|
// to homogeneous coords
|
|
29
39
|
p.set(worldPos);
|
|
30
40
|
p[3] = 1;
|
|
@@ -227,7 +227,7 @@ class MetaModel {
|
|
|
227
227
|
this.metaScene.metaObjects[id] = metaObject;
|
|
228
228
|
metaObject.metaModels = [];
|
|
229
229
|
}
|
|
230
|
-
this.metaObjects[id] =metaObject;
|
|
230
|
+
this.metaObjects[id] = metaObject;
|
|
231
231
|
if (!metaObjectData.parent) {
|
|
232
232
|
this.rootMetaObjects.push(metaObject);
|
|
233
233
|
metaScene.rootMetaObjects[id] = metaObject;
|
|
@@ -185,13 +185,12 @@ class MetaScene {
|
|
|
185
185
|
// Remove MetaObjects
|
|
186
186
|
|
|
187
187
|
if (metaModel.metaObjects) {
|
|
188
|
-
for (let
|
|
189
|
-
const metaObject = metaModel.metaObjects[
|
|
190
|
-
const id = metaObject.id;
|
|
188
|
+
for (let objectId in metaModel.metaObjects) {
|
|
189
|
+
const metaObject = metaModel.metaObjects[objectId];
|
|
191
190
|
if (metaObject.metaModels.length === 1 && metaObject.metaModels[0].id === metaModelId) { // MetaObject owned only by this model, delete
|
|
192
|
-
delete this.metaObjects[
|
|
191
|
+
delete this.metaObjects[objectId];
|
|
193
192
|
if (!metaObject.parent) {
|
|
194
|
-
delete this.rootMetaObjects[
|
|
193
|
+
delete this.rootMetaObjects[objectId];
|
|
195
194
|
}
|
|
196
195
|
} else {
|
|
197
196
|
metaObject.metaModels = metaObject.metaModels.filter(metaModel => metaModel.id !== metaModelId);
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import {Viewer, Component} from "../../viewer";
|
|
2
|
+
import {ObjectsKdTree3} from "../collision";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Picks a {@link Viewer}'s {@link Entity}s with a canvas-space 2D marquee box.
|
|
6
|
+
*
|
|
7
|
+
* [<img src="https://xeokit.github.io/xeokit-sdk/assets/images/MarqueeSelect.gif">](https://xeokit.github.io/xeokit-sdk/examples/picking/#marqueePick_select)
|
|
8
|
+
*
|
|
9
|
+
* * [[Example 1: Select Objects with Marquee](https://xeokit.github.io/xeokit-sdk/examples/picking/#marqueePick_select)]
|
|
10
|
+
* * [[Example 2: View-Fit Objects with Marquee](https://xeokit.github.io/xeokit-sdk/examples/picking/#marqueePick_viewFit)]
|
|
11
|
+
*
|
|
12
|
+
* # Usage
|
|
13
|
+
*
|
|
14
|
+
* In the example below, we
|
|
15
|
+
*
|
|
16
|
+
* 1. Create a {@link Viewer}, arrange the {@link Camera}
|
|
17
|
+
* 2. Use an {@link XKTLoaderPlugin} to load a BIM model,
|
|
18
|
+
* 3. Create a {@link ObjectsKdTree3} to automatically index the `Viewer's` {@link Entity}s for fast spatial lookup,
|
|
19
|
+
* 4. Create a `MarqueePicker` to pick {@link Entity}s in the {@link Viewer}, using the {@link ObjectsKdTree3} to accelerate picking
|
|
20
|
+
* 5. Create a {@link MarqueePickerMouseControl} to perform the marquee-picking with the `MarqueePicker`, using mouse input to draw the marquee box on the `Viewer's` canvas.
|
|
21
|
+
*
|
|
22
|
+
* When the {@link MarqueePickerMouseControl} is active:
|
|
23
|
+
*
|
|
24
|
+
* * Long-click, drag and release on the canvas to define a marque box that picks {@link Entity}s.
|
|
25
|
+
* * Drag left-to-right to pick {@link Entity}s that intersect the box.
|
|
26
|
+
* * Drag right-to-left to pick {@link Entity}s that are fully inside the box.
|
|
27
|
+
* * On release, the `MarqueePicker` will fire a "picked" event with IDs of the picked {@link Entity}s, if any.
|
|
28
|
+
* * Handling that event, we mark the {@link Entity}s as selected.
|
|
29
|
+
* * Hold down CTRL to multi-pick.
|
|
30
|
+
*
|
|
31
|
+
* ````javascript
|
|
32
|
+
* import {
|
|
33
|
+
* Viewer,
|
|
34
|
+
* XKTLoaderPlugin,
|
|
35
|
+
* ObjectsKdTree3,
|
|
36
|
+
* MarqueePicker,
|
|
37
|
+
* MarqueePickerMouseControl
|
|
38
|
+
* } from "xeokit-sdk.es.js";
|
|
39
|
+
*
|
|
40
|
+
* // 1
|
|
41
|
+
*
|
|
42
|
+
* const viewer = new Viewer({
|
|
43
|
+
* canvasId: "myCanvas"
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* viewer.scene.camera.eye = [14.9, 14.3, 5.4];
|
|
47
|
+
* viewer.scene.camera.look = [6.5, 8.3, -4.1];
|
|
48
|
+
* viewer.scene.camera.up = [-0.28, 0.9, -0.3];
|
|
49
|
+
*
|
|
50
|
+
* // 2
|
|
51
|
+
*
|
|
52
|
+
* const xktLoader = new XKTLoaderPlugin(viewer);
|
|
53
|
+
*
|
|
54
|
+
* const sceneModel = xktLoader.load({
|
|
55
|
+
* id: "myModel",
|
|
56
|
+
* src: "../../assets/models/xkt/v8/ifc/HolterTower.ifc.xkt"
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* // 3
|
|
60
|
+
*
|
|
61
|
+
* const objectsKdTree3 = new ObjectsKdTree3({viewer});
|
|
62
|
+
*
|
|
63
|
+
* // 4
|
|
64
|
+
*
|
|
65
|
+
* const marqueePicker = new MarqueePicker({viewer, objectsKdTree3});
|
|
66
|
+
*
|
|
67
|
+
* // 5
|
|
68
|
+
*
|
|
69
|
+
* const marqueePickerMouseControl = new MarqueePickerMouseControl({marqueePicker});
|
|
70
|
+
*
|
|
71
|
+
* marqueePicker.on("clear", () => {
|
|
72
|
+
* viewer.scene.setObjectsSelected(viewer.scene.selectedObjectIds, false);
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
* marqueePicker.on("picked", (objectIds) => {
|
|
76
|
+
* viewer.scene.setObjectsSelected(objectIds, true);
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* marqueePickerMouseControl.setActive(true);
|
|
80
|
+
* ````
|
|
81
|
+
*
|
|
82
|
+
* # Design Notes
|
|
83
|
+
*
|
|
84
|
+
* * The {@link ObjectsKdTree3} can be shared with any other components that want to use it to spatially search for {@link Entity}s.
|
|
85
|
+
* * The {@link MarqueePickerMouseControl} can be replaced with other types of controllers (i.e. touch), or used alongside them.
|
|
86
|
+
* * The `MarqueePicker` has no input handlers of its own, and provides an API through which to programmatically control marquee picking. By firing the "picked" events, `MarqueePicker` implements the *Blackboard Pattern*.
|
|
87
|
+
*/
|
|
88
|
+
export class MarqueePicker extends Component {
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Pick mode that picks {@link Entity}s that intersect the marquee box.
|
|
92
|
+
*
|
|
93
|
+
* @type {number}
|
|
94
|
+
*/
|
|
95
|
+
static PICK_MODE_INTERSECTS: number;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Pick mode that picks {@link Entity}s that are completely inside the marquee box.
|
|
99
|
+
*
|
|
100
|
+
* @type {number}
|
|
101
|
+
*/
|
|
102
|
+
static PICK_MODE_INSIDE: number;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Creates a MarqueePicker.
|
|
106
|
+
*
|
|
107
|
+
* @param {*} cfg Configuration
|
|
108
|
+
* @param {Viewer} cfg.viewer The Viewer to pick Entities from.
|
|
109
|
+
* @param {ObjectsKdTree3} cfg.objectsKdTree3 A k-d tree that indexes the Entities in the Viewer for fast spatial lookup.
|
|
110
|
+
*/
|
|
111
|
+
constructor(cfg: {
|
|
112
|
+
viewer: Viewer;
|
|
113
|
+
objectsKdTree3: ObjectsKdTree3;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Sets the canvas-space position of the first marquee box corner.
|
|
118
|
+
*
|
|
119
|
+
* @param corner1
|
|
120
|
+
*/
|
|
121
|
+
setMarqueeCorner1(corner1: number[]): void;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Sets the canvas-space position of the second marquee box corner.
|
|
125
|
+
*
|
|
126
|
+
* @param corner2
|
|
127
|
+
*/
|
|
128
|
+
setMarqueeCorner2(corner2: number[]):void;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Sets both canvas-space corner positions of the marquee box.
|
|
132
|
+
*
|
|
133
|
+
* @param corner1
|
|
134
|
+
* @param corner2
|
|
135
|
+
*/
|
|
136
|
+
setMarquee(corner1: number[], corner2: number[]):void;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Sets if the marquee box is visible.
|
|
140
|
+
*
|
|
141
|
+
* @param {boolean} visible True if the marquee box is to be visible, else false.
|
|
142
|
+
*/
|
|
143
|
+
setMarqueeVisible(visible:boolean):void;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Gets if the marquee box is visible.
|
|
147
|
+
*
|
|
148
|
+
* @returns {boolean} True if the marquee box is visible, else false.
|
|
149
|
+
*/
|
|
150
|
+
getMarqueeVisible() :boolean;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Sets the pick mode.
|
|
154
|
+
*
|
|
155
|
+
* Supported pick modes are:
|
|
156
|
+
*
|
|
157
|
+
* * MarqueePicker.PICK_MODE_INSIDE - picks {@link Entity}s that are completely inside the marquee box.
|
|
158
|
+
* * MarqueePicker.PICK_MODE_INTERSECTS - picks {@link Entity}s that intersect the marquee box.
|
|
159
|
+
*
|
|
160
|
+
* @param {number} pickMode The pick mode.
|
|
161
|
+
*/
|
|
162
|
+
setPickMode(pickMode: number) :void;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Gets the pick mode.
|
|
166
|
+
*
|
|
167
|
+
* Supported pick modes are:
|
|
168
|
+
*
|
|
169
|
+
* * MarqueePicker.PICK_MODE_INSIDE - picks {@link Entity}s that are completely inside the marquee box.
|
|
170
|
+
* * MarqueePicker.PICK_MODE_INTERSECTS - picks {@link Entity}s that intersect the marquee box.
|
|
171
|
+
*
|
|
172
|
+
* @returns {number} The pick mode.
|
|
173
|
+
*/
|
|
174
|
+
getPickMode() :number;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Fires a "clear" event on this MarqueePicker.
|
|
178
|
+
*/
|
|
179
|
+
clear() :void;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Attempts to pick {@link Entity}s, using the current MarquePicker settings.
|
|
183
|
+
*
|
|
184
|
+
* Fires a "picked" event with the IDs of the {@link Entity}s that were picked, if any.
|
|
185
|
+
*
|
|
186
|
+
* @returns {string[]} IDs of the {@link Entity}s that were picked, if any
|
|
187
|
+
*/
|
|
188
|
+
pick():string[];
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Destroys this MarqueePicker.
|
|
193
|
+
*
|
|
194
|
+
* Does not destroy the {@link Viewer} or the {@link ObjectsKdTree3} provided to the constructor of this MarqueePicker.
|
|
195
|
+
*/
|
|
196
|
+
destroy():void;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {Component} from "../../viewer";
|
|
2
|
+
import {MarqueePicker} from "./MarqueePicker";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Controls a {@link MarqueePicker} with mouse input.
|
|
6
|
+
*
|
|
7
|
+
* See {@link MarqueePicker} for usage example.
|
|
8
|
+
*
|
|
9
|
+
* When the MarqueePickerMouseControl is active:
|
|
10
|
+
*
|
|
11
|
+
* * Long-click, drag and release on the canvas to define a marque box that picks {@link Entity}s.
|
|
12
|
+
* * Drag left-to-right to pick Entities that intersect the box.
|
|
13
|
+
* * Drag right-to-left to pick Entities that are fully inside the box.
|
|
14
|
+
* * On release, the MarqueePicker will fire a "picked" event with IDs of the picked Entities , if any.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export class MarqueePickerMouseControl extends Component {
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new MarqueePickerMouseControl.
|
|
22
|
+
*
|
|
23
|
+
* @param {*} cfg Configuration
|
|
24
|
+
* @param {MarqueePicker} cfg.marqueePicker The MarqueePicker to control.
|
|
25
|
+
*/
|
|
26
|
+
constructor(cfg: {
|
|
27
|
+
marqueePicker: MarqueePicker;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Activates or deactivates this MarqueePickerMouseControl.
|
|
32
|
+
*
|
|
33
|
+
* @param {boolean} active Whether or not to activate.
|
|
34
|
+
*/
|
|
35
|
+
setActive(active: boolean): void;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Gets if this MarqueePickerMouseControl is active.
|
|
39
|
+
*
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
getActive(): boolean;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
*/
|
|
47
|
+
destroy(): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {Viewer} from "../../viewer";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Automatically indexes a {@link Viewer}'s {@link Entity}s in a 3D k-d tree
|
|
5
|
+
* to support fast collision detection with 3D World-space axis-aligned boundaries (AABBs) and frustums.
|
|
6
|
+
*
|
|
7
|
+
* See {@link MarqueePicker} for usage example.
|
|
8
|
+
*
|
|
9
|
+
* An ObjectsKdTree3 is configured with a Viewer, and will then automatically
|
|
10
|
+
* keep itself populated with k-d nodes that contain the Viewer's Entitys.
|
|
11
|
+
*
|
|
12
|
+
* We can then traverse the k-d nodes, starting at {@link ObjectsKdTree3#root}, to find
|
|
13
|
+
* the contained Entities.
|
|
14
|
+
*/
|
|
15
|
+
export class ObjectsKdTree3 {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creates an ObjectsKdTree3.
|
|
19
|
+
*
|
|
20
|
+
* @param {*} cfg Configuration
|
|
21
|
+
* @param {Viewer} cfg.viewer The Viewer that provides the {@link Entity}s in this ObjectsKdTree3.
|
|
22
|
+
* @param {number} [cfg.maxTreeDepth=15] Optional maximum depth for the k-d tree.
|
|
23
|
+
*/
|
|
24
|
+
constructor(cfg: {
|
|
25
|
+
viewer: Viewer;
|
|
26
|
+
maxTreeDepth?: number;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Gets the root ObjectsKdTree3 node.
|
|
31
|
+
*
|
|
32
|
+
* Each time this accessor is accessed, it will lazy-rebuild the ObjectsKdTree3
|
|
33
|
+
* if {@link Entity}s have been created or removed in the {@link Viewer} since the last time it was accessed.
|
|
34
|
+
*/
|
|
35
|
+
get root(): any;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Destroys this ObjectsKdTree3.
|
|
39
|
+
*
|
|
40
|
+
* Does not destroy the {@link Viewer} given to the constructor of the ObjectsKdTree3.
|
|
41
|
+
*/
|
|
42
|
+
destroy(): void
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ObjectsKdTree3";
|
package/types/extras/index.d.ts
CHANGED