@xeokit/xeokit-sdk 2.6.63 → 2.6.65

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.
Files changed (27) hide show
  1. package/dist/xeokit-sdk.cjs.js +592 -1237
  2. package/dist/xeokit-sdk.es.js +592 -1237
  3. package/dist/xeokit-sdk.es5.js +155 -197
  4. package/dist/xeokit-sdk.min.cjs.js +5 -5
  5. package/dist/xeokit-sdk.min.es.js +5 -5
  6. package/dist/xeokit-sdk.min.es5.js +4 -4
  7. package/package.json +1 -1
  8. package/src/extras/PointerLens/PointerLens.js +27 -46
  9. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +29 -20
  10. package/src/plugins/AnnotationsPlugin/Annotation.js +3 -0
  11. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +27 -33
  12. package/src/plugins/SectionPlanesPlugin/Control.js +462 -1142
  13. package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +10 -4
  14. package/src/plugins/lib/html/MenuEvent.js +3 -1
  15. package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +1 -2
  16. package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +1 -1
  17. package/types/plugins/AngleMeasurementsPlugin/index.d.ts +2 -1
  18. package/types/plugins/CityJSONLoaderPlugin/CityJSONLoaderPlugin.d.ts +4 -0
  19. package/types/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.d.ts +121 -0
  20. package/types/plugins/DotBIMLoaderPlugin/index.d.ts +1 -0
  21. package/types/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.d.ts +4 -0
  22. package/types/plugins/LASLoaderPlugin/LASLoaderPlugin.d.ts +4 -0
  23. package/types/plugins/STLLoaderPlugin/STLLoaderPlugin.d.ts +4 -0
  24. package/types/plugins/TreeViewPlugin/TreeViewPlugin.d.ts +4 -0
  25. package/types/plugins/WebIFCLoaderPlugin/WebIFCLoaderPlugin.d.ts +4 -0
  26. package/types/plugins/XKTLoaderPlugin/XKTLoaderPlugin.d.ts +19 -1
  27. package/types/plugins/index.d.ts +1 -0
@@ -10,6 +10,7 @@ import {Node} from "../../viewer/scene/nodes/Node.js";
10
10
  import {Mesh} from "../../viewer/scene/mesh/Mesh.js";
11
11
  import {buildSphereGeometry} from "../../viewer/scene/geometry/builders/buildSphereGeometry.js";
12
12
  import {worldToRTCPos} from "../../viewer/scene/math/rtcCoords.js";
13
+ import {transformToNode} from "../lib/ui/index.js";
13
14
 
14
15
  const zeroVec = new Float64Array([0, 0, 1]);
15
16
  const quat = new Float64Array(4);
@@ -34,874 +35,412 @@ class Control {
34
35
  */
35
36
  this.id = null;
36
37
 
37
- this._viewer = plugin.viewer;
38
+ const viewer = plugin.viewer;
39
+ const camera = viewer.camera;
40
+ const cameraControl = viewer.cameraControl;
41
+ const scene = viewer.scene;
42
+ const canvas = scene.canvas.canvas;
38
43
 
39
44
  this._visible = false;
40
- this._pos = math.vec3(); // Full-precision position of the center of the Control
41
- this._origin = math.vec3();
42
- this._rtcPos = math.vec3();
43
-
44
- this._baseDir = math.vec3(); // Saves direction of clip plane when we start dragging an arrow or ring.
45
- this._rootNode = null; // Root of Node graph that represents this control in the 3D scene
46
- this._displayMeshes = null; // Meshes that are always visible
47
- this._affordanceMeshes = null; // Meshes displayed momentarily for affordance
48
-
49
- this._ignoreNextSectionPlaneDirUpdate = false;
50
-
51
- this._createNodes();
52
- this._bindEvents();
53
- }
54
-
55
- /**
56
- * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.
57
- * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.
58
- * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.
59
- * @private
60
- */
61
- _setSectionPlane(sectionPlane) {
62
- if (this._sectionPlane) {
63
- this._sectionPlane.off(this._onSectionPlanePos);
64
- this._sectionPlane.off(this._onSectionPlaneDir);
65
- this._onSectionPlanePos = null;
66
- this._onSectionPlaneDir = null;
67
- this._sectionPlane = null;
68
- }
69
- if (sectionPlane) {
70
- this.id = sectionPlane.id;
71
- this._setPos(sectionPlane.pos);
72
- this._setDir(sectionPlane.dir);
73
- this._sectionPlane = sectionPlane;
74
- this._onSectionPlanePos = sectionPlane.on("pos", () => {
75
- this._setPos(this._sectionPlane.pos);
76
- });
77
- this._onSectionPlaneDir = sectionPlane.on("dir", () => {
78
- if (!this._ignoreNextSectionPlaneDirUpdate) {
79
- this._setDir(this._sectionPlane.dir);
80
- } else {
81
- this._ignoreNextSectionPlaneDirUpdate = false;
82
- }
83
- });
84
- }
85
- }
86
-
87
- /**
88
- * Gets the {@link SectionPlane} controlled by this Control.
89
- * @returns {SectionPlane} The SectionPlane.
90
- */
91
- get sectionPlane() {
92
- return this._sectionPlane;
93
- }
94
-
95
- /** @private */
96
- _setPos(xyz) {
97
45
 
98
- this._pos.set(xyz);
99
-
100
- worldToRTCPos(this._pos, this._origin, this._rtcPos);
101
-
102
- this._rootNode.origin = this._origin;
103
- this._rootNode.position = this._rtcPos;
104
- }
105
-
106
- /** @private */
107
- _setDir(xyz) {
108
- this._baseDir.set(xyz);
109
- this._rootNode.quaternion = math.vec3PairToQuaternion(zeroVec, xyz, quat);
110
- }
111
-
112
- _setSectionPlaneDir(dir) {
113
- if (this._sectionPlane) {
114
- this._ignoreNextSectionPlaneDirUpdate = true;
115
- this._sectionPlane.dir = dir;
116
- }
117
- }
118
-
119
- /**
120
- * Sets if this Control is visible.
121
- *
122
- * @type {Boolean}
123
- */
124
- setVisible(visible = true) {
125
- if (this._visible === visible) {
126
- return;
127
- }
128
- this._visible = visible;
129
- var id;
130
- for (id in this._displayMeshes) {
131
- if (this._displayMeshes.hasOwnProperty(id)) {
132
- this._displayMeshes[id].visible = visible;
133
- }
134
- }
135
- if (!visible) {
136
- for (id in this._affordanceMeshes) {
137
- if (this._affordanceMeshes.hasOwnProperty(id)) {
138
- this._affordanceMeshes[id].visible = visible;
139
- }
140
- }
141
- }
142
- }
143
-
144
- /**
145
- * Gets if this Control is visible.
146
- *
147
- * @type {Boolean}
148
- */
149
- getVisible() {
150
- return this._visible;
151
- }
152
-
153
- /**
154
- * Sets if this Control is culled. This is called by SectionPlanesPlugin to
155
- * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().
156
- * @param culled
157
- */
158
- setCulled(culled) {
159
- var id;
160
- for (id in this._displayMeshes) {
161
- if (this._displayMeshes.hasOwnProperty(id)) {
162
- this._displayMeshes[id].culled = culled;
163
- }
164
- }
165
- if (!culled) {
166
- for (id in this._affordanceMeshes) {
167
- if (this._affordanceMeshes.hasOwnProperty(id)) {
168
- this._affordanceMeshes[id].culled = culled;
169
- }
170
- }
171
- }
172
- }
173
-
174
- /**
175
- * Builds the Entities that represent this Control.
176
- * @private
177
- */
178
- _createNodes() {
46
+ let ignoreNextSectionPlaneDirUpdate = false;
179
47
 
48
+ // Builds the Entities that represent this Control.
180
49
  const NO_STATE_INHERIT = false;
181
- const scene = this._viewer.scene;
182
- const radius = 1.0;
183
- const handleTubeRadius = 0.06;
184
- const hoopRadius = radius - 0.2;
50
+ const arrowLength = 1.0;
51
+ const handleRadius = 0.09;
185
52
  const tubeRadius = 0.01;
186
- const arrowRadius = 0.07;
187
53
 
188
- this._rootNode = new Node(scene, {
54
+ const rootNode = new Node(scene, { // Root of Node graph that represents this control in the 3D scene
189
55
  position: [0, 0, 0],
190
56
  scale: [5, 5, 5],
191
57
  isObject: false
192
58
  });
193
59
 
194
- const rootNode = this._rootNode;
60
+ const pos = math.vec3();
61
+ const setPos = (function() {
62
+ const origin = math.vec3();
63
+ const rtcPos = math.vec3();
64
+ return function(p) {
65
+ pos.set(p);
66
+ worldToRTCPos(p, origin, rtcPos);
67
+ rootNode.origin = origin;
68
+ rootNode.position = rtcPos;
69
+ };
70
+ })();
195
71
 
196
- const shapes = {// Reusable geometries
72
+ const arrowGeometry = (radiusBottom, height) => new ReadableGeometry(rootNode, buildCylinderGeometry({
73
+ radiusTop: 0.001,
74
+ radiusBottom: radiusBottom,
75
+ radialSegments: 32,
76
+ heightSegments: 1,
77
+ height: height,
78
+ openEnded: false
79
+ }));
80
+
81
+ const tubeGeometry = (radius, height, radialSegments) => new ReadableGeometry(rootNode, buildCylinderGeometry({
82
+ radiusTop: radius,
83
+ radiusBottom: radius,
84
+ radialSegments: radialSegments,
85
+ heightSegments: 1,
86
+ height: height,
87
+ openEnded: false
88
+ }));
89
+
90
+ const torusGeometry = (tube, arcFraction, tubeSegments) => new ReadableGeometry(rootNode, buildTorusGeometry({
91
+ radius: arrowLength - 0.2,
92
+ tube: tube,
93
+ radialSegments: 64,
94
+ tubeSegments: tubeSegments,
95
+ arc: (Math.PI * 2.0) * arcFraction
96
+ }));
197
97
 
198
- arrowHead: new ReadableGeometry(rootNode, buildCylinderGeometry({
199
- radiusTop: 0.001,
200
- radiusBottom: arrowRadius,
201
- radialSegments: 32,
202
- heightSegments: 1,
203
- height: 0.2,
204
- openEnded: false
205
- })),
206
-
207
- arrowHeadBig: new ReadableGeometry(rootNode, buildCylinderGeometry({
208
- radiusTop: 0.001,
209
- radiusBottom: 0.09,
210
- radialSegments: 32,
211
- heightSegments: 1,
212
- height: 0.25,
213
- openEnded: false
214
- })),
215
-
216
- arrowHeadHandle: new ReadableGeometry(rootNode, buildCylinderGeometry({
217
- radiusTop: 0.09,
218
- radiusBottom: 0.09,
219
- radialSegments: 8,
220
- heightSegments: 1,
221
- height: 0.37,
222
- openEnded: false
223
- })),
224
-
225
- curve: new ReadableGeometry(rootNode, buildTorusGeometry({
226
- radius: hoopRadius,
227
- tube: tubeRadius,
228
- radialSegments: 64,
229
- tubeSegments: 14,
230
- arc: (Math.PI * 2.0) / 4.0
231
- })),
232
-
233
- curveHandle: new ReadableGeometry(rootNode, buildTorusGeometry({
234
- radius: hoopRadius,
235
- tube: handleTubeRadius,
236
- radialSegments: 64,
237
- tubeSegments: 14,
238
- arc: (Math.PI * 2.0) / 4.0
239
- })),
240
-
241
- hoop: new ReadableGeometry(rootNode, buildTorusGeometry({
242
- radius: hoopRadius,
243
- tube: tubeRadius,
244
- radialSegments: 64,
245
- tubeSegments: 8,
246
- arc: (Math.PI * 2.0)
247
- })),
248
-
249
- axis: new ReadableGeometry(rootNode, buildCylinderGeometry({
250
- radiusTop: tubeRadius,
251
- radiusBottom: tubeRadius,
252
- radialSegments: 20,
253
- heightSegments: 1,
254
- height: radius,
255
- openEnded: false
256
- })),
257
-
258
- axisHandle: new ReadableGeometry(rootNode, buildCylinderGeometry({
259
- radiusTop: 0.08,
260
- radiusBottom: 0.08,
261
- radialSegments: 20,
262
- heightSegments: 1,
263
- height: radius,
264
- openEnded: false
265
- }))
266
- };
98
+ const shapes = {// Reusable geometries
267
99
 
268
- const materials = { // Reusable materials
269
-
270
- pickable: new PhongMaterial(rootNode, { // Invisible material for pickable handles, which define a pickable 3D area
271
- diffuse: [1, 1, 0],
272
- alpha: 0, // Invisible
273
- alphaMode: "blend"
274
- }),
275
-
276
- red: new PhongMaterial(rootNode, {
277
- diffuse: [1, 0.0, 0.0],
278
- emissive: [1, 0.0, 0.0],
279
- ambient: [0.0, 0.0, 0.0],
280
- specular: [.6, .6, .3],
281
- shininess: 80,
282
- lineWidth: 2
283
- }),
284
-
285
- highlightRed: new EmphasisMaterial(rootNode, { // Emphasis for red rotation affordance hoop
286
- edges: false,
287
- fill: true,
288
- fillColor: [1, 0, 0],
289
- fillAlpha: 0.6
290
- }),
291
-
292
- green: new PhongMaterial(rootNode, {
293
- diffuse: [0.0, 1, 0.0],
294
- emissive: [0.0, 1, 0.0],
295
- ambient: [0.0, 0.0, 0.0],
296
- specular: [.6, .6, .3],
297
- shininess: 80,
298
- lineWidth: 2
299
- }),
300
-
301
- highlightGreen: new EmphasisMaterial(rootNode, { // Emphasis for green rotation affordance hoop
302
- edges: false,
303
- fill: true,
304
- fillColor: [0, 1, 0],
305
- fillAlpha: 0.6
306
- }),
307
-
308
- blue: new PhongMaterial(rootNode, {
309
- diffuse: [0.0, 0.0, 1],
310
- emissive: [0.0, 0.0, 1],
311
- ambient: [0.0, 0.0, 0.0],
312
- specular: [.6, .6, .3],
313
- shininess: 80,
314
- lineWidth: 2
315
- }),
316
-
317
- highlightBlue: new EmphasisMaterial(rootNode, { // Emphasis for blue rotation affordance hoop
318
- edges: false,
319
- fill: true,
320
- fillColor: [0, 0, 1],
321
- fillAlpha: 0.2
322
- }),
323
-
324
- center: new PhongMaterial(rootNode, {
325
- diffuse: [0.0, 0.0, 0.0],
326
- emissive: [0, 0, 0],
327
- ambient: [0.0, 0.0, 0.0],
328
- specular: [.6, .6, .3],
329
- shininess: 80
330
- }),
331
-
332
- highlightBall: new EmphasisMaterial(rootNode, {
333
- edges: false,
334
- fill: true,
335
- fillColor: [0.5, 0.5, 0.5],
336
- fillAlpha: 0.5,
337
- vertices: false
338
- }),
339
-
340
- highlightPlane: new EmphasisMaterial(rootNode, {
341
- edges: true,
342
- edgeWidth: 3,
343
- fill: false,
344
- fillColor: [0.5, 0.5, .5],
345
- fillAlpha: 0.5,
346
- vertices: false
347
- })
348
- };
100
+ curve: torusGeometry(tubeRadius, 0.25, 14),
101
+ curveHandle: torusGeometry(handleRadius, 0.25, 14),
102
+ hoop: torusGeometry(tubeRadius, 1, 8),
349
103
 
350
- this._displayMeshes = {
104
+ arrowHead: arrowGeometry(0.07, 0.2),
105
+ arrowHeadBig: arrowGeometry(0.09, 0.25),
106
+ arrowHeadHandle: tubeGeometry(handleRadius, 0.37, 8),
351
107
 
352
- plane: rootNode.addChild(new Mesh(rootNode, {
353
- geometry: new ReadableGeometry(rootNode, {
354
- primitive: "triangles",
355
- positions: [
356
- 0.5, 0.5, 0.0, 0.5, -0.5, 0.0, // 0
357
- -0.5, -0.5, 0.0, -0.5, 0.5, 0.0, // 1
358
- 0.5, 0.5, -0.0, 0.5, -0.5, -0.0, // 2
359
- -0.5, -0.5, -0.0, -0.5, 0.5, -0.0 // 3
360
- ],
361
- indices: [0, 1, 2, 2, 3, 0]
362
- }),
363
- material: new PhongMaterial(rootNode, {
364
- emissive: [0, 0.0, 0],
365
- diffuse: [0, 0, 0],
366
- backfaces: true
367
- }),
368
- opacity: 0.6,
369
- ghosted: true,
370
- ghostMaterial: new EmphasisMaterial(rootNode, {
371
- edges: false,
372
- filled: true,
373
- fillColor: [1, 1, 0],
374
- edgeColor: [0, 0, 0],
375
- fillAlpha: 0.1,
376
- backfaces: true
377
- }),
378
- pickable: false,
379
- collidable: true,
380
- clippable: false,
381
- visible: false,
382
- scale: [2.4, 2.4, 1],
383
- isObject: false
384
- }), NO_STATE_INHERIT),
108
+ axis: tubeGeometry(tubeRadius, arrowLength, 20),
109
+ axisHandle: tubeGeometry(handleRadius, arrowLength, 20)
110
+ };
385
111
 
386
- planeFrame: rootNode.addChild(new Mesh(rootNode, { // Visible frame
387
- geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
388
- center: [0, 0, 0],
389
- radius: 1.7,
390
- tube: tubeRadius * 2,
391
- radialSegments: 4,
392
- tubeSegments: 4,
393
- arc: Math.PI * 2.0
394
- })),
395
- material: new PhongMaterial(rootNode, {
396
- emissive: [0, 0, 0],
397
- diffuse: [0, 0, 0],
398
- specular: [0, 0, 0],
399
- shininess: 0
400
- }),
401
- //highlighted: true,
402
- highlightMaterial: new EmphasisMaterial(rootNode, {
403
- edges: false,
404
- edgeColor: [0.0, 0.0, 0.0],
405
- filled: true,
406
- fillColor: [0.8, 0.8, 0.8],
407
- fillAlpha: 1.0
408
- }),
409
- pickable: false,
410
- collidable: false,
411
- clippable: false,
412
- visible: false,
413
- scale: [1, 1, .1],
414
- rotation: [0, 0, 45],
415
- isObject: false
416
- }), NO_STATE_INHERIT),
112
+ const colorMaterial = (rgb) => new PhongMaterial(rootNode, {
113
+ diffuse: rgb,
114
+ emissive: rgb,
115
+ ambient: [0.0, 0.0, 0.0],
116
+ specular: [.6, .6, .3],
117
+ shininess: 80,
118
+ lineWidth: 2
119
+ });
417
120
 
418
- //----------------------------------------------------------------------------------------------------------
419
- //
420
- //----------------------------------------------------------------------------------------------------------
121
+ const highlightMaterial = (rgb, fillAlpha) => new EmphasisMaterial(rootNode, {
122
+ edges: false,
123
+ fill: true,
124
+ fillColor: rgb,
125
+ fillAlpha: fillAlpha
126
+ });
421
127
 
422
- xCurve: rootNode.addChild(new Mesh(rootNode, { // Red hoop about Y-axis
423
- geometry: shapes.curve,
424
- material: materials.red,
425
- matrix: (function () {
426
- const rotate2 = math.rotationMat4v(90 * math.DEGTORAD, [0, 1, 0], math.identityMat4());
427
- const rotate1 = math.rotationMat4v(270 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
428
- return math.mulMat4(rotate1, rotate2, math.identityMat4());
429
- })(),
430
- pickable: false,
431
- collidable: true,
432
- clippable: false,
433
- backfaces: true,
434
- visible: false,
435
- isObject: false
436
- }), NO_STATE_INHERIT),
128
+ const pickableMaterial = new PhongMaterial(rootNode, { // Invisible material for pickable handles, which define a pickable 3D area
129
+ diffuse: [1, 1, 0],
130
+ alpha: 0, // Invisible
131
+ alphaMode: "blend"
132
+ });
437
133
 
438
- xCurveHandle: rootNode.addChild(new Mesh(rootNode, { // Red hoop about Y-axis
439
- geometry: shapes.curveHandle,
440
- material: materials.pickable,
441
- matrix: (function () {
442
- const rotate2 = math.rotationMat4v(90 * math.DEGTORAD, [0, 1, 0], math.identityMat4());
443
- const rotate1 = math.rotationMat4v(270 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
444
- return math.mulMat4(rotate1, rotate2, math.identityMat4());
445
- })(),
446
- pickable: true,
447
- collidable: true,
448
- clippable: false,
449
- backfaces: true,
450
- visible: false,
451
- isObject: false
452
- }), NO_STATE_INHERIT),
134
+ const handlers = { };
135
+ const addAxis = (rgb, axisDirection, hoopDirection) => {
136
+ const material = colorMaterial(rgb);
453
137
 
454
- xCurveArrow1: rootNode.addChild(new Mesh(rootNode, {
455
- geometry: shapes.arrowHead,
456
- material: materials.red,
457
- matrix: (function () {
458
- const translate = math.translateMat4c(0., -0.07, -0.8, math.identityMat4());
459
- const scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());
460
- const rotate = math.rotationMat4v(0 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
461
- return math.mulMat4(math.mulMat4(translate, scale, math.identityMat4()), rotate, math.identityMat4());
462
- })(),
463
- pickable: true,
464
- collidable: true,
465
- clippable: false,
466
- visible: false,
467
- isObject: false
468
- }), NO_STATE_INHERIT),
138
+ const rotateToHorizontal = math.rotationMat4v(270 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
139
+ const hoopRotation = math.quaternionToRotationMat4(math.vec3PairToQuaternion([ 0, 1, 0 ], hoopDirection), math.identityMat4());
140
+ const hoopMatrix = math.mulMat4(hoopRotation, rotateToHorizontal, math.identityMat4());
469
141
 
470
- xCurveArrow2: rootNode.addChild(new Mesh(rootNode, {
471
- geometry: shapes.arrowHead,
472
- material: materials.red,
473
- matrix: (function () {
474
- const translate = math.translateMat4c(0.0, -0.8, -0.07, math.identityMat4());
475
- const scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());
476
- const rotate = math.rotationMat4v(90 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
477
- return math.mulMat4(math.mulMat4(translate, scale, math.identityMat4()), rotate, math.identityMat4());
478
- })(),
479
- pickable: true,
480
- collidable: true,
481
- clippable: false,
482
- visible: false,
483
- isObject: false
484
- }), NO_STATE_INHERIT),
142
+ const scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());
485
143
 
486
- //----------------------------------------------------------------------------------------------------------
487
- //
488
- //----------------------------------------------------------------------------------------------------------
144
+ const scaledArrowMatrix = (t, matR) => {
145
+ const matT = math.translateMat4v(t, math.identityMat4());
146
+ const ret = math.identityMat4();
147
+ math.mulMat4(matT, matR, ret);
148
+ math.mulMat4(hoopMatrix, ret, ret);
149
+ return math.mulMat4(ret, scale, math.identityMat4());
150
+ };
489
151
 
490
- yCurve: rootNode.addChild(new Mesh(rootNode, {
152
+ const curve = rootNode.addChild(new Mesh(rootNode, {
491
153
  geometry: shapes.curve,
492
- material: materials.green,
493
- rotation: [-90, 0, 0],
154
+ material: material,
155
+ matrix: hoopMatrix,
494
156
  pickable: false,
495
157
  collidable: true,
496
158
  clippable: false,
497
159
  backfaces: true,
498
160
  visible: false,
499
161
  isObject: false
500
- }), NO_STATE_INHERIT),
162
+ }), NO_STATE_INHERIT);
501
163
 
502
- yCurveHandle: rootNode.addChild(new Mesh(rootNode, {
164
+ const rotateHandle = rootNode.addChild(new Mesh(rootNode, {
503
165
  geometry: shapes.curveHandle,
504
- material: materials.pickable,
505
- rotation: [-90, 0, 0],
166
+ material: pickableMaterial,
167
+ matrix: hoopMatrix,
506
168
  pickable: true,
507
169
  collidable: true,
508
170
  clippable: false,
509
171
  backfaces: true,
510
172
  visible: false,
511
173
  isObject: false
512
- }), NO_STATE_INHERIT),
174
+ }), NO_STATE_INHERIT);
513
175
 
514
- yCurveArrow1: rootNode.addChild(new Mesh(rootNode, {
176
+ const arrow1 = rootNode.addChild(new Mesh(rootNode, {
515
177
  geometry: shapes.arrowHead,
516
- material: materials.green,
517
- matrix: (function () {
518
- const translate = math.translateMat4c(0.07, 0, -0.8, math.identityMat4());
519
- const scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());
520
- const rotate = math.rotationMat4v(90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
521
- return math.mulMat4(math.mulMat4(translate, scale, math.identityMat4()), rotate, math.identityMat4());
522
- })(),
178
+ material: material,
179
+ matrix: scaledArrowMatrix([ .8, .07, 0 ], math.rotationMat4v(180 * math.DEGTORAD, [0, 0, 1], math.identityMat4())),
523
180
  pickable: true,
524
181
  collidable: true,
525
182
  clippable: false,
526
183
  visible: false,
527
184
  isObject: false
528
- }), NO_STATE_INHERIT),
185
+ }), NO_STATE_INHERIT);
529
186
 
530
- yCurveArrow2: rootNode.addChild(new Mesh(rootNode, {
187
+ const arrow2 = rootNode.addChild(new Mesh(rootNode, {
531
188
  geometry: shapes.arrowHead,
532
- material: materials.green,
533
- matrix: (function () {
534
- const translate = math.translateMat4c(0.8, 0.0, -0.07, math.identityMat4());
535
- const scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());
536
- const rotate = math.rotationMat4v(90 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
537
- return math.mulMat4(math.mulMat4(translate, scale, math.identityMat4()), rotate, math.identityMat4());
538
- })(),
189
+ material: material,
190
+ matrix: scaledArrowMatrix([ .07, .8, 0 ], math.rotationMat4v(90 * math.DEGTORAD, [0, 0, 1], math.identityMat4())),
539
191
  pickable: true,
540
192
  collidable: true,
541
193
  clippable: false,
542
194
  visible: false,
543
195
  isObject: false
544
- }), NO_STATE_INHERIT),
196
+ }), NO_STATE_INHERIT);
545
197
 
546
- //----------------------------------------------------------------------------------------------------------
547
- //
548
- //----------------------------------------------------------------------------------------------------------
549
-
550
- zCurve: rootNode.addChild(new Mesh(rootNode, { // Blue hoop about Z-axis
551
- geometry: shapes.curve,
552
- material: materials.blue,
553
- matrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),
554
- pickable: false,
555
- collidable: true,
556
- clippable: false,
557
- visible: false,
558
- isObject: false
559
- }), NO_STATE_INHERIT),
560
-
561
- zCurveHandle: rootNode.addChild(new Mesh(rootNode, {
562
- geometry: shapes.curveHandle,
563
- material: materials.pickable,
564
- matrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),
565
- pickable: true,
566
- collidable: true,
567
- clippable: false,
568
- visible: false,
569
- isObject: false
570
- }), NO_STATE_INHERIT),
571
-
572
- zCurveCurveArrow1: rootNode.addChild(new Mesh(rootNode, {
573
- geometry: shapes.arrowHead,
574
- material: materials.blue,
575
- matrix: (function () {
576
- const translate = math.translateMat4c(.8, -0.07, 0, math.identityMat4());
577
- const scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());
578
- return math.mulMat4(translate, scale, math.identityMat4());
579
- })(),
580
- pickable: true,
581
- collidable: true,
582
- clippable: false,
583
- visible: false,
584
- isObject: false
585
- }), NO_STATE_INHERIT),
586
-
587
- zCurveArrow2: rootNode.addChild(new Mesh(rootNode, {
588
- geometry: shapes.arrowHead,
589
- material: materials.blue,
590
- matrix: (function () {
591
- const translate = math.translateMat4c(.05, -0.8, 0, math.identityMat4());
592
- const scale = math.scaleMat4v([0.6, 0.6, 0.6], math.identityMat4());
593
- const rotate = math.rotationMat4v(90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
594
- return math.mulMat4(math.mulMat4(translate, scale, math.identityMat4()), rotate, math.identityMat4());
595
- })(),
596
- pickable: true,
597
- collidable: true,
598
- clippable: false,
599
- visible: false,
600
- isObject: false
601
- }), NO_STATE_INHERIT),
602
-
603
- //----------------------------------------------------------------------------------------------------------
604
- //
605
- //----------------------------------------------------------------------------------------------------------
606
-
607
- center: rootNode.addChild(new Mesh(rootNode, {
608
- geometry: new ReadableGeometry(rootNode, buildSphereGeometry({
609
- radius: 0.05
610
- })),
611
- material: materials.center,
612
- pickable: false,
613
- collidable: true,
614
- clippable: false,
615
- visible: false,
616
- isObject: false
617
- }), NO_STATE_INHERIT),
618
-
619
- //----------------------------------------------------------------------------------------------------------
620
- //
621
- //----------------------------------------------------------------------------------------------------------
622
-
623
- xAxisArrow: rootNode.addChild(new Mesh(rootNode, {
624
- geometry: shapes.arrowHead,
625
- material: materials.red,
626
- matrix: (function () {
627
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
628
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
629
- return math.mulMat4(rotate, translate, math.identityMat4());
630
- })(),
198
+ const hoop = rootNode.addChild(new Mesh(rootNode, {
199
+ geometry: shapes.hoop,
200
+ material: material,
201
+ highlighted: true,
202
+ highlightMaterial: highlightMaterial(rgb, 0.6),
203
+ matrix: hoopMatrix,
631
204
  pickable: false,
632
205
  collidable: true,
633
206
  clippable: false,
634
207
  visible: false,
635
208
  isObject: false
636
- }), NO_STATE_INHERIT),
209
+ }), NO_STATE_INHERIT);
637
210
 
638
- xAxisArrowHandle: rootNode.addChild(new Mesh(rootNode, {
639
- geometry: shapes.arrowHeadHandle,
640
- material: materials.pickable,
641
- matrix: (function () {
642
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
643
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
644
- return math.mulMat4(rotate, translate, math.identityMat4());
645
- })(),
646
- pickable: true,
647
- collidable: true,
648
- clippable: false,
649
- visible: false,
650
- isObject: false
651
- }), NO_STATE_INHERIT),
652
211
 
653
- xAxis: rootNode.addChild(new Mesh(rootNode, {
654
- geometry: shapes.axis,
655
- material: materials.red,
656
- matrix: (function () {
657
- const translate = math.translateMat4c(0, radius / 2, 0, math.identityMat4());
658
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
659
- return math.mulMat4(rotate, translate, math.identityMat4());
660
- })(),
661
- pickable: false,
662
- collidable: true,
663
- clippable: false,
664
- visible: false,
665
- isObject: false
666
- }), NO_STATE_INHERIT),
212
+ const axisRotation = math.quaternionToRotationMat4(math.vec3PairToQuaternion([ 0, 1, 0 ], axisDirection), math.identityMat4());
667
213
 
668
- xAxisHandle: rootNode.addChild(new Mesh(rootNode, {
669
- geometry: shapes.axisHandle,
670
- material: materials.pickable,
671
- matrix: (function () {
672
- const translate = math.translateMat4c(0, radius / 2, 0, math.identityMat4());
673
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
674
- return math.mulMat4(rotate, translate, math.identityMat4());
675
- })(),
676
- pickable: true,
677
- collidable: true,
678
- clippable: false,
679
- visible: false,
680
- isObject: false
681
- }), NO_STATE_INHERIT),
682
-
683
- //----------------------------------------------------------------------------------------------------------
684
- //
685
- //----------------------------------------------------------------------------------------------------------
214
+ const translatedAxisMatrix = (yOffset) => math.mulMat4(axisRotation, math.translateMat4c(0, yOffset, 0, math.identityMat4()), math.identityMat4());
215
+ const arrowMatrix = translatedAxisMatrix(arrowLength + .1);
216
+ const shaftMatrix = translatedAxisMatrix(arrowLength / 2);
686
217
 
687
- yAxisArrow: rootNode.addChild(new Mesh(rootNode, {
218
+ const arrow = rootNode.addChild(new Mesh(rootNode, {
688
219
  geometry: shapes.arrowHead,
689
- material: materials.green,
690
- matrix: (function () {
691
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
692
- const rotate = math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
693
- return math.mulMat4(rotate, translate, math.identityMat4());
694
- })(),
220
+ material: material,
221
+ matrix: arrowMatrix,
695
222
  pickable: false,
696
223
  collidable: true,
697
224
  clippable: false,
698
225
  visible: false,
699
226
  isObject: false
700
- }), NO_STATE_INHERIT),
227
+ }), NO_STATE_INHERIT);
701
228
 
702
- yAxisArrowHandle: rootNode.addChild(new Mesh(rootNode, {
229
+ const arrowHandle = rootNode.addChild(new Mesh(rootNode, {
703
230
  geometry: shapes.arrowHeadHandle,
704
- material: materials.pickable,
705
- matrix: (function () {
706
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
707
- const rotate = math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
708
- return math.mulMat4(rotate, translate, math.identityMat4());
709
- })(),
231
+ material: pickableMaterial,
232
+ matrix: arrowMatrix,
710
233
  pickable: true,
711
234
  collidable: true,
712
235
  clippable: false,
713
236
  visible: false,
714
- opacity: 0.2,
715
237
  isObject: false
716
- }), NO_STATE_INHERIT),
238
+ }), NO_STATE_INHERIT);
717
239
 
718
- yShaft: rootNode.addChild(new Mesh(rootNode, {
240
+ const shaft = rootNode.addChild(new Mesh(rootNode, {
719
241
  geometry: shapes.axis,
720
- material: materials.green,
721
- position: [0, -radius / 2, 0],
242
+ material: material,
243
+ matrix: shaftMatrix,
722
244
  pickable: false,
723
245
  collidable: true,
724
246
  clippable: false,
725
247
  visible: false,
726
248
  isObject: false
727
- }), NO_STATE_INHERIT),
249
+ }), NO_STATE_INHERIT);
728
250
 
729
- yShaftHandle: rootNode.addChild(new Mesh(rootNode, {
251
+ const shaftHandle = rootNode.addChild(new Mesh(rootNode, {
730
252
  geometry: shapes.axisHandle,
731
- material: materials.pickable,
732
- position: [0, -radius / 2, 0],
253
+ material: pickableMaterial,
254
+ matrix: shaftMatrix,
733
255
  pickable: true,
734
256
  collidable: true,
735
257
  clippable: false,
736
258
  visible: false,
737
259
  isObject: false
738
- }), NO_STATE_INHERIT),
739
-
740
- //----------------------------------------------------------------------------------------------------------
741
- //
742
- //----------------------------------------------------------------------------------------------------------
260
+ }), NO_STATE_INHERIT);
743
261
 
744
- zAxisArrow: rootNode.addChild(new Mesh(rootNode, {
745
- geometry: shapes.arrowHead,
746
- material: materials.blue,
747
- matrix: (function () {
748
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
749
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0.8, 0, 0], math.identityMat4());
750
- return math.mulMat4(rotate, translate, math.identityMat4());
751
- })(),
262
+ const bigArrowHead = rootNode.addChild(new Mesh(rootNode, {
263
+ geometry: shapes.arrowHeadBig,
264
+ material: material,
265
+ matrix: arrowMatrix,
752
266
  pickable: false,
753
267
  collidable: true,
754
268
  clippable: false,
755
269
  visible: false,
756
270
  isObject: false
757
- }), NO_STATE_INHERIT),
271
+ }), NO_STATE_INHERIT);
758
272
 
759
- zAxisArrowHandle: rootNode.addChild(new Mesh(rootNode, {
760
- geometry: shapes.arrowHeadHandle,
761
- material: materials.pickable,
762
- matrix: (function () {
763
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
764
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0.8, 0, 0], math.identityMat4());
765
- return math.mulMat4(rotate, translate, math.identityMat4());
766
- })(),
767
- pickable: true,
768
- collidable: true,
769
- clippable: false,
770
- visible: false,
771
- isObject: false
772
- }), NO_STATE_INHERIT),
273
+ const localToWorldVec = (localVec, worldVec) => math.vec3ApplyQuaternion(rootNode.quaternion, localVec, worldVec);
773
274
 
275
+ const closestPointOnAxis = (function() {
276
+ const worldAxis = math.vec3();
277
+ const org = math.vec3();
278
+ const dir = math.vec3();
279
+ return (canvasPos, dst) => {
280
+ localToWorldVec(rgb, worldAxis);
774
281
 
775
- zShaft: rootNode.addChild(new Mesh(rootNode, {
776
- geometry: shapes.axis,
777
- material: materials.blue,
778
- matrix: (function () {
779
- const translate = math.translateMat4c(0, radius / 2, 0, math.identityMat4());
780
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
781
- return math.mulMat4(rotate, translate, math.identityMat4());
782
- })(),
783
- clippable: false,
282
+ const P = pos;
283
+ const D = worldAxis;
284
+
285
+ math.canvasPosToWorldRay(canvas, scene.camera.viewMatrix, scene.camera.projMatrix, scene.camera.projection, canvasPos, org, dir);
286
+
287
+ const d01 = math.dotVec3(D, dir);
288
+ const v = math.subVec3(org, P, dst);
289
+ const v0 = math.dotVec3(v, D);
290
+ const v1 = math.dotVec3(v, dir);
291
+ const det = 1 - d01 * d01;
292
+
293
+ if (Math.abs(det) > 1e-10) { // if lines are not parallel
294
+ const s = (v0 - d01 * v1) / det;
295
+ math.addVec3(P, math.mulVec3Scalar(D, s, dst), dst);
296
+ return true;
297
+ } else {
298
+ return false;
299
+ }
300
+ };
301
+ })();
302
+ const initOffset = math.vec3();
303
+ const tempVec3 = math.vec3();
304
+ handlers[arrowHandle.id] = handlers[shaftHandle.id] = {
305
+ setActivated: a => bigArrowHead.visible = a,
306
+ initDragAction: (initCanvasPos) => {
307
+ return closestPointOnAxis(initCanvasPos, initOffset) && math.subVec3(initOffset, pos, initOffset) && ((canvasPos) => {
308
+ if (closestPointOnAxis(canvasPos, tempVec3)) {
309
+ math.subVec3(tempVec3, initOffset, tempVec3);
310
+ setPos(tempVec3);
311
+ if (this._sectionPlane) {
312
+ this._sectionPlane.pos = tempVec3;
313
+ }
314
+ }
315
+ });
316
+ }
317
+ };
318
+
319
+ handlers[rotateHandle.id] = {
320
+ setActivated: a => hoop.visible = a,
321
+ initDragAction: (initCanvasPos) => {
322
+ const rotationFromCanvasPos = (function() {
323
+ const planeCanvasPos = camera.projectWorldPos(pos);
324
+ localToWorldVec(rgb, tempVec3);
325
+ math.transformVec3(camera.normalMatrix, tempVec3, tempVec3);
326
+ const axisCoeff = Math.sign(tempVec3[2]);
327
+ return (canvasPos) => {
328
+ const dx = canvasPos[0] - planeCanvasPos[0];
329
+ const dy = canvasPos[1] - planeCanvasPos[1];
330
+ return axisCoeff * Math.atan2(-dy, dx);
331
+ };
332
+ })();
333
+
334
+ let lastRotation = rotationFromCanvasPos(initCanvasPos);
335
+
336
+ return canvasPos => {
337
+ const rotation = rotationFromCanvasPos(canvasPos);
338
+ rootNode.rotate(rgb, (rotation - lastRotation) * 180 / Math.PI);
339
+ if (this._sectionPlane) {
340
+ ignoreNextSectionPlaneDirUpdate = true;
341
+ this._sectionPlane.dir = math.vec3ApplyQuaternion(rootNode.quaternion, [0, 0, 1], tempVec3);
342
+ }
343
+ lastRotation = rotation;
344
+ };
345
+ }
346
+ };
347
+
348
+ return {
349
+ set visible(v) {
350
+ arrow.visible = arrowHandle.visible = shaft.visible = shaftHandle.visible = curve.visible = rotateHandle.visible = arrow1.visible = arrow2.visible = v;
351
+ if (! v) {
352
+ bigArrowHead.visible = v;
353
+ hoop.visible = v;
354
+ }
355
+ },
356
+ set culled(c) {
357
+ arrow.culled = arrowHandle.culled = shaft.culled = shaftHandle.culled = curve.culled = rotateHandle.culled = arrow1.culled = arrow2.culled = c;
358
+ if (! c) {
359
+ bigArrowHead.culled = c;
360
+ hoop.culled = c;
361
+ }
362
+ }
363
+ };
364
+ };
365
+
366
+ this._displayMeshes = [ // Meshes that are always visible
367
+ rootNode.addChild(new Mesh(rootNode, { // plane
368
+ geometry: new ReadableGeometry(rootNode, {
369
+ primitive: "triangles",
370
+ positions: [
371
+ 0.5, 0.5, 0.0, 0.5, -0.5, 0.0, // 0
372
+ -0.5, -0.5, 0.0, -0.5, 0.5, 0.0, // 1
373
+ 0.5, 0.5, -0.0, 0.5, -0.5, -0.0, // 2
374
+ -0.5, -0.5, -0.0, -0.5, 0.5, -0.0 // 3
375
+ ],
376
+ indices: [0, 1, 2, 2, 3, 0]
377
+ }),
378
+ material: new PhongMaterial(rootNode, {
379
+ emissive: [0, 0.0, 0],
380
+ diffuse: [0, 0, 0],
381
+ backfaces: true
382
+ }),
383
+ opacity: 0.6,
384
+ ghosted: true,
385
+ ghostMaterial: new EmphasisMaterial(rootNode, {
386
+ edges: false,
387
+ filled: true,
388
+ fillColor: [1, 1, 0],
389
+ edgeColor: [0, 0, 0],
390
+ fillAlpha: 0.1,
391
+ backfaces: true
392
+ }),
784
393
  pickable: false,
785
394
  collidable: true,
786
- visible: false,
787
- isObject: false
788
- }), NO_STATE_INHERIT),
789
-
790
- zAxisHandle: rootNode.addChild(new Mesh(rootNode, {
791
- geometry: shapes.axisHandle,
792
- material: materials.pickable,
793
- matrix: (function () {
794
- const translate = math.translateMat4c(0, radius / 2, 0, math.identityMat4());
795
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
796
- return math.mulMat4(rotate, translate, math.identityMat4());
797
- })(),
798
395
  clippable: false,
799
- pickable: true,
800
- collidable: true,
801
396
  visible: false,
397
+ scale: [2.4, 2.4, 1],
802
398
  isObject: false
803
- }), NO_STATE_INHERIT)
804
- };
805
-
806
- this._affordanceMeshes = {
399
+ }), NO_STATE_INHERIT),
807
400
 
808
- planeFrame: rootNode.addChild(new Mesh(rootNode, {
401
+ rootNode.addChild(new Mesh(rootNode, { // Visible frame
809
402
  geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
810
403
  center: [0, 0, 0],
811
- radius: 2,
812
- tube: tubeRadius,
404
+ radius: 1.7,
405
+ tube: tubeRadius * 2,
813
406
  radialSegments: 4,
814
407
  tubeSegments: 4,
815
408
  arc: Math.PI * 2.0
816
409
  })),
817
410
  material: new PhongMaterial(rootNode, {
818
- ambient: [1, 1, 1],
411
+ emissive: [0, 0, 0],
819
412
  diffuse: [0, 0, 0],
820
- emissive: [1, 1, 0]
413
+ specular: [0, 0, 0],
414
+ shininess: 0
821
415
  }),
822
- highlighted: true,
416
+ //highlighted: true,
823
417
  highlightMaterial: new EmphasisMaterial(rootNode, {
824
418
  edges: false,
419
+ edgeColor: [0.0, 0.0, 0.0],
825
420
  filled: true,
826
- fillColor: [1, 1, 0],
421
+ fillColor: [0.8, 0.8, 0.8],
827
422
  fillAlpha: 1.0
828
423
  }),
829
424
  pickable: false,
830
425
  collidable: false,
831
426
  clippable: false,
832
427
  visible: false,
833
- scale: [1, 1, 1],
428
+ scale: [1, 1, .1],
834
429
  rotation: [0, 0, 45],
835
430
  isObject: false
836
431
  }), NO_STATE_INHERIT),
837
432
 
838
- xHoop: rootNode.addChild(new Mesh(rootNode, { // Full
839
- geometry: shapes.hoop,
840
- material: materials.red,
841
- highlighted: true,
842
- highlightMaterial: materials.highlightRed,
843
- matrix: (function () {
844
- const rotate2 = math.rotationMat4v(90 * math.DEGTORAD, [0, 1, 0], math.identityMat4());
845
- const rotate1 = math.rotationMat4v(270 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
846
- return math.mulMat4(rotate1, rotate2, math.identityMat4());
847
- })(),
848
- pickable: false,
849
- collidable: true,
850
- clippable: false,
851
- visible: false,
852
- isObject: false
853
- }), NO_STATE_INHERIT),
854
-
855
- yHoop: rootNode.addChild(new Mesh(rootNode, {
856
- geometry: shapes.hoop,
857
- material: materials.green,
858
- highlighted: true,
859
- highlightMaterial: materials.highlightGreen,
860
- rotation: [-90, 0, 0],
861
- pickable: false,
862
- collidable: true,
863
- clippable: false,
864
- visible: false,
865
- isObject: false
866
- }), NO_STATE_INHERIT),
867
-
868
- zHoop: rootNode.addChild(new Mesh(rootNode, { // Blue hoop about Z-axis
869
- geometry: shapes.hoop,
870
- material: materials.blue,
871
- highlighted: true,
872
- highlightMaterial: materials.highlightBlue,
873
- matrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),
874
- pickable: false,
875
- collidable: true,
876
- clippable: false,
877
- backfaces: true,
878
- visible: false,
879
- isObject: false
880
- }), NO_STATE_INHERIT),
881
-
882
- xAxisArrow: rootNode.addChild(new Mesh(rootNode, {
883
- geometry: shapes.arrowHeadBig,
884
- material: materials.red,
885
- matrix: (function () {
886
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
887
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0, 0, 1], math.identityMat4());
888
- return math.mulMat4(rotate, translate, math.identityMat4());
889
- })(),
890
- pickable: false,
891
- collidable: true,
892
- clippable: false,
893
- visible: false,
894
- isObject: false
895
- }), NO_STATE_INHERIT),
896
-
897
- yAxisArrow: rootNode.addChild(new Mesh(rootNode, {
898
- geometry: shapes.arrowHeadBig,
899
- material: materials.green,
900
- matrix: (function () {
901
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
902
- const rotate = math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
903
- return math.mulMat4(rotate, translate, math.identityMat4());
904
- })(),
433
+ rootNode.addChild(new Mesh(rootNode, { // center
434
+ geometry: new ReadableGeometry(rootNode, buildSphereGeometry({
435
+ radius: 0.05
436
+ })),
437
+ material: new PhongMaterial(rootNode, {
438
+ diffuse: [0.0, 0.0, 0.0],
439
+ emissive: [0, 0, 0],
440
+ ambient: [0.0, 0.0, 0.0],
441
+ specular: [.6, .6, .3],
442
+ shininess: 80
443
+ }),
905
444
  pickable: false,
906
445
  collidable: true,
907
446
  clippable: false,
@@ -909,455 +448,236 @@ class Control {
909
448
  isObject: false
910
449
  }), NO_STATE_INHERIT),
911
450
 
912
- zAxisArrow: rootNode.addChild(new Mesh(rootNode, {
913
- geometry: shapes.arrowHeadBig,
914
- material: materials.blue,
915
- matrix: (function () {
916
- const translate = math.translateMat4c(0, radius + .1, 0, math.identityMat4());
917
- const rotate = math.rotationMat4v(-90 * math.DEGTORAD, [0.8, 0, 0], math.identityMat4());
918
- return math.mulMat4(rotate, translate, math.identityMat4());
919
- })(),
920
- pickable: false,
921
- collidable: true,
922
- clippable: false,
923
- visible: false,
924
- isObject: false
925
- }), NO_STATE_INHERIT)
926
- };
927
- }
928
-
929
- _bindEvents() {
930
-
931
- const self = this;
932
-
933
- var grabbed = false;
934
-
935
- const DRAG_ACTIONS = {
936
- none: -1,
937
- xTranslate: 0,
938
- yTranslate: 1,
939
- zTranslate: 2,
940
- xRotate: 3,
941
- yRotate: 4,
942
- zRotate: 5
943
- };
944
-
945
- const rootNode = this._rootNode;
946
-
947
- var nextDragAction = null; // As we hover grabbed an arrow or hoop, self is the action we would do if we then dragged it.
948
- var dragAction = null; // Action we're doing while we drag an arrow or hoop.
949
- const lastCanvasPos = math.vec2();
451
+ //----------------------------------------------------------------------------------------------------------
452
+ //
453
+ //----------------------------------------------------------------------------------------------------------
950
454
 
951
- const xBaseAxis = math.vec3([1, 0, 0]);
952
- const yBaseAxis = math.vec3([0, 1, 0]);
953
- const zBaseAxis = math.vec3([0, 0, 1]);
455
+ addAxis([1,0,0], [ 1, 0, 0 ], [ 1, 0, 0 ]),
456
+ addAxis([0,1,0], [ 0, -1, 0 ], [ 0, 1, 0 ]),
457
+ addAxis([0,0,1], [ 0, 0, -1 ], [ 0, 0, -1 ])
458
+ ];
954
459
 
955
- const canvas = this._viewer.scene.canvas.canvas;
956
- const camera = this._viewer.camera;
957
- const scene = this._viewer.scene;
460
+ const cleanups = [ ];
958
461
 
959
462
  { // Keep gizmo screen size constant
960
-
961
- const tempVec3a = math.vec3([0, 0, 0]);
962
-
963
- let distDirty = true;
964
463
  let lastDist = -1;
965
-
966
- this._onCameraViewMatrix = scene.camera.on("viewMatrix", () => {
967
- distDirty = true;
968
- });
969
-
970
- this._onCameraProjMatrix = scene.camera.on("projMatrix", () => {
971
- distDirty = true;
972
- });
973
-
974
- this._onSceneTick = scene.on("tick", () => {
975
-
976
- const dist = Math.abs(math.lenVec3(math.subVec3(scene.camera.eye, this._pos, tempVec3a)));
977
-
978
- if (dist !== lastDist) {
979
- if (camera.projection === "perspective") {
980
- const worldSize = (Math.tan(camera.perspective.fov * math.DEGTORAD)) * dist;
981
- const size = 0.07 * worldSize;
982
- rootNode.scale = [size, size, size];
983
- lastDist = dist;
464
+ const setRootNodeScale = size => rootNode.scale = [size, size, size];
465
+ const onSceneTick = scene.on("tick", () => {
466
+ const dist = Math.abs(math.distVec3(camera.eye, pos));
467
+ if (camera.projection === "perspective") {
468
+ if (dist !== lastDist) {
469
+ setRootNodeScale(0.07 * dist * Math.tan(camera.perspective.fov * math.DEGTORAD));
984
470
  }
471
+ } else if (camera.projection === "ortho") {
472
+ setRootNodeScale(camera.ortho.scale / 10);
985
473
  }
986
-
987
- if (camera.projection === "ortho") {
988
- const worldSize = camera.ortho.scale / 10;
989
- const size = worldSize;
990
- rootNode.scale = [size, size, size];
991
- lastDist = dist;
992
- }
474
+ lastDist = dist;
993
475
  });
476
+ cleanups.push(() => scene.off(onSceneTick));
994
477
  }
995
478
 
996
- const getClickCoordsWithinElement = (function () {
997
- const canvasPos = new Float64Array(2);
998
- return function (event) {
999
- if (!event) {
1000
- event = window.event;
1001
- canvasPos[0] = event.x;
1002
- canvasPos[1] = event.y;
1003
- } else {
1004
- var element = event.target;
1005
- var totalOffsetLeft = 0;
1006
- var totalOffsetTop = 0;
1007
-
1008
- while (element.offsetParent) {
1009
- totalOffsetLeft += element.offsetLeft;
1010
- totalOffsetTop += element.offsetTop;
1011
- element = element.offsetParent;
1012
- }
1013
- canvasPos[0] = event.pageX - totalOffsetLeft;
1014
- canvasPos[1] = event.pageY - totalOffsetTop;
1015
- }
1016
- return canvasPos;
479
+ {
480
+ let deactivateActive = null;
481
+ let currentDrag = null;
482
+ cleanups.push(() => { if (currentDrag) { currentDrag.cleanup(); } });
483
+ const canvasPos = math.vec2();
484
+
485
+ const copyCanvasPos = (event, vec2) => {
486
+ vec2[0] = event.clientX;
487
+ vec2[1] = event.clientY;
488
+ transformToNode(canvas.ownerDocument.documentElement, canvas, vec2);
1017
489
  };
1018
- })();
1019
490
 
1020
- const localToWorldVec = (function () {
1021
- const mat = math.mat4();
1022
- return function (localVec, worldVec) {
1023
- math.quaternionToMat4(self._rootNode.quaternion, mat);
1024
- math.transformVec3(mat, localVec, worldVec);
1025
- math.normalizeVec3(worldVec);
1026
- return worldVec;
491
+ const pickHandler = (e) => {
492
+ copyCanvasPos(e, canvasPos);
493
+ const pickResult = viewer.scene.pick({ canvasPos: canvasPos });
494
+ const pickEntity = pickResult && pickResult.entity;
495
+ const pickId = pickEntity && pickEntity.id;
496
+ return (pickId in handlers) && handlers[pickId];
1027
497
  };
1028
- })();
1029
498
 
1030
- var getTranslationPlane = (function () {
1031
- const planeNormal = math.vec3();
1032
- return function (worldAxis) {
1033
- const absX = Math.abs(worldAxis[0]);
1034
- if (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {
1035
- math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);
1036
- } else {
1037
- math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);
1038
- }
1039
- math.cross3Vec3(planeNormal, worldAxis, planeNormal);
1040
- math.normalizeVec3(planeNormal);
1041
- return planeNormal;
1042
- }
1043
- })();
1044
-
1045
- const dragTranslateSectionPlane = (function () {
1046
- const p1 = math.vec3();
1047
- const p2 = math.vec3();
1048
- const worldAxis = math.vec4();
1049
- return function (baseAxis, fromMouse, toMouse) {
1050
- localToWorldVec(baseAxis, worldAxis);
1051
- const planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);
1052
- getPointerPlaneIntersect(fromMouse, planeNormal, p1);
1053
- getPointerPlaneIntersect(toMouse, planeNormal, p2);
1054
- math.subVec3(p2, p1);
1055
- const dot = math.dotVec3(p2, worldAxis);
1056
- self._pos[0] += worldAxis[0] * dot;
1057
- self._pos[1] += worldAxis[1] * dot;
1058
- self._pos[2] += worldAxis[2] * dot;
1059
- self._rootNode.position = self._pos;
1060
- if (self._sectionPlane) {
1061
- self._sectionPlane.pos = self._pos;
1062
- }
1063
- }
1064
- })();
1065
-
1066
- var dragRotateSectionPlane = (function () {
1067
- const p1 = math.vec4();
1068
- const p2 = math.vec4();
1069
- const c = math.vec4();
1070
- const worldAxis = math.vec4();
1071
- return function (baseAxis, fromMouse, toMouse) {
1072
- localToWorldVec(baseAxis, worldAxis);
1073
- const hasData = getPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);
1074
- if (!hasData) { // Find intersections with view plane and project down to origin
1075
- const planeNormal = getTranslationPlane(worldAxis, fromMouse, toMouse);
1076
- getPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable
1077
- getPointerPlaneIntersect(toMouse, planeNormal, p2, 1);
1078
- var dot = math.dotVec3(p1, worldAxis);
1079
- p1[0] -= dot * worldAxis[0];
1080
- p1[1] -= dot * worldAxis[1];
1081
- p1[2] -= dot * worldAxis[2];
1082
- dot = math.dotVec3(p2, worldAxis);
1083
- p2[0] -= dot * worldAxis[0];
1084
- p2[1] -= dot * worldAxis[1];
1085
- p2[2] -= dot * worldAxis[2];
1086
- }
1087
- math.normalizeVec3(p1);
1088
- math.normalizeVec3(p2);
1089
- dot = math.dotVec3(p1, p2);
1090
- dot = math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range
1091
- var incDegrees = Math.acos(dot) * math.RADTODEG;
1092
- math.cross3Vec3(p1, p2, c);
1093
- if (math.dotVec3(c, worldAxis) < 0.0) {
1094
- incDegrees = -incDegrees;
1095
- }
1096
- self._rootNode.rotate(baseAxis, incDegrees);
1097
- rotateSectionPlane();
1098
- }
1099
- })();
499
+ const startDrag = (event, matchesEvent) => {
500
+ const handler = pickHandler(matchesEvent(event));
501
+ if (handler) {
502
+ if (currentDrag) {
503
+ currentDrag.cleanup();
504
+ }
1100
505
 
1101
- var getPointerPlaneIntersect = (function () {
1102
- const dir = math.vec4([0, 0, 0, 1]);
1103
- const matrix = math.mat4();
1104
- return function (mouse, axis, dest, offset) {
1105
- offset = offset || 0;
1106
- dir[0] = mouse[0] / canvas.width * 2.0 - 1.0;
1107
- dir[1] = -(mouse[1] / canvas.height * 2.0 - 1.0);
1108
- dir[2] = 0.0;
1109
- dir[3] = 1.0;
1110
- math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords
1111
- math.inverseMat4(matrix);
1112
- math.transformVec4(matrix, dir, dir);
1113
- math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space
1114
- var rayO = camera.eye; // The direction
1115
- math.subVec4(dir, rayO, dir);
1116
- const origin = self._sectionPlane.pos; // Plane origin:
1117
- var d = -math.dotVec3(origin, axis) - offset;
1118
- var dot = math.dotVec3(axis, dir);
1119
- if (Math.abs(dot) > 0.005) {
1120
- var t = -(math.dotVec3(axis, rayO) + d) / dot;
1121
- math.mulVec3Scalar(dir, t, dest);
1122
- math.addVec3(dest, rayO);
1123
- math.subVec3(dest, origin, dest);
1124
- return true;
506
+ const dragAction = handler.initDragAction(canvasPos);
507
+ if (dragAction) {
508
+ cameraControl.pointerEnabled = false; // or .active = false ?
509
+ handler.setActivated(true);
510
+
511
+ currentDrag = {
512
+ onChange: event => {
513
+ const e = matchesEvent(event);
514
+ if (e) {
515
+ copyCanvasPos(e, canvasPos);
516
+ dragAction(canvasPos);
517
+ }
518
+ },
519
+ cleanup: function() {
520
+ currentDrag = null;
521
+ cameraControl.pointerEnabled = true; // or .active = true ?
522
+ handler.setActivated(false);
523
+ }
524
+ };
525
+ }
1125
526
  }
1126
- return false;
1127
- }
1128
- })();
527
+ };
1129
528
 
1130
- const rotateSectionPlane = (function () {
1131
- const dir = math.vec3();
1132
- const mat = math.mat4();
1133
- return function () {
1134
- if (self.sectionPlane) {
1135
- math.quaternionToMat4(rootNode.quaternion, mat); // << ---
1136
- math.transformVec3(mat, [0, 0, 1], dir);
1137
- self._setSectionPlaneDir(dir);
1138
- }
529
+ const addCanvasEventListener = (type, listener) => {
530
+ canvas.addEventListener(type, listener);
531
+ cleanups.push(() => canvas.removeEventListener(type, listener));
1139
532
  };
1140
- })();
1141
533
 
1142
- {
1143
- var mouseDownLeft;
1144
- var mouseDownMiddle;
1145
- var mouseDownRight;
1146
- var down = false;
1147
- var lastAffordanceMesh;
1148
-
1149
- this._onCameraControlHover = this._viewer.cameraControl.on("hoverEnter", (hit) => {
1150
- if (!this._visible) {
1151
- return;
1152
- }
1153
- if (down) {
1154
- return;
1155
- }
1156
- grabbed = false;
1157
- if (lastAffordanceMesh) {
1158
- lastAffordanceMesh.visible = false;
1159
- }
1160
- var affordanceMesh;
1161
- const meshId = hit.entity.id;
1162
- switch (meshId) {
1163
-
1164
- case this._displayMeshes.xAxisArrowHandle.id:
1165
- affordanceMesh = this._affordanceMeshes.xAxisArrow;
1166
- nextDragAction = DRAG_ACTIONS.xTranslate;
1167
- break;
1168
-
1169
- case this._displayMeshes.xAxisHandle.id:
1170
- affordanceMesh = this._affordanceMeshes.xAxisArrow;
1171
- nextDragAction = DRAG_ACTIONS.xTranslate;
1172
- break;
1173
-
1174
- case this._displayMeshes.yAxisArrowHandle.id:
1175
- affordanceMesh = this._affordanceMeshes.yAxisArrow;
1176
- nextDragAction = DRAG_ACTIONS.yTranslate;
1177
- break;
1178
-
1179
- case this._displayMeshes.yShaftHandle.id:
1180
- affordanceMesh = this._affordanceMeshes.yAxisArrow;
1181
- nextDragAction = DRAG_ACTIONS.yTranslate;
1182
- break;
1183
-
1184
- case this._displayMeshes.zAxisArrowHandle.id:
1185
- affordanceMesh = this._affordanceMeshes.zAxisArrow;
1186
- nextDragAction = DRAG_ACTIONS.zTranslate;
1187
- break;
1188
-
1189
- case this._displayMeshes.zAxisHandle.id:
1190
- affordanceMesh = this._affordanceMeshes.zAxisArrow;
1191
- nextDragAction = DRAG_ACTIONS.zTranslate;
1192
- break;
1193
-
1194
- case this._displayMeshes.xCurveHandle.id:
1195
- affordanceMesh = this._affordanceMeshes.xHoop;
1196
- nextDragAction = DRAG_ACTIONS.xRotate;
1197
- break;
1198
-
1199
- case this._displayMeshes.yCurveHandle.id:
1200
- affordanceMesh = this._affordanceMeshes.yHoop;
1201
- nextDragAction = DRAG_ACTIONS.yRotate;
1202
- break;
1203
-
1204
- case this._displayMeshes.zCurveHandle.id:
1205
- affordanceMesh = this._affordanceMeshes.zHoop;
1206
- nextDragAction = DRAG_ACTIONS.zRotate;
1207
- break;
1208
-
1209
- default:
1210
- nextDragAction = DRAG_ACTIONS.none;
1211
- return; // Not clicked an arrow or hoop
1212
- }
1213
- if (affordanceMesh) {
1214
- affordanceMesh.visible = true;
534
+ addCanvasEventListener("mousedown", (e) => {
535
+ e.preventDefault();
536
+ if (e.which === 1) {
537
+ startDrag(e, event => (event.which === 1) && event);
1215
538
  }
1216
- lastAffordanceMesh = affordanceMesh;
1217
- grabbed = true;
1218
539
  });
1219
540
 
1220
- this._onCameraControlHoverLeave = this._viewer.cameraControl.on("hoverOutEntity", (hit) => {
1221
- if (!this._visible) {
1222
- return;
1223
- }
1224
- if (lastAffordanceMesh) {
1225
- lastAffordanceMesh.visible = false;
541
+ addCanvasEventListener("mousemove", (e) => {
542
+ if (currentDrag) {
543
+ currentDrag.onChange(e);
544
+ } else {
545
+ if (deactivateActive) {
546
+ deactivateActive();
547
+ }
548
+ const handler = pickHandler(e);
549
+ if (handler) {
550
+ handler.setActivated(true);
551
+ deactivateActive = () => handler.setActivated(false);
552
+ } else {
553
+ deactivateActive = null;
554
+ }
1226
555
  }
1227
- lastAffordanceMesh = null;
1228
- nextDragAction = DRAG_ACTIONS.none;
1229
556
  });
1230
557
 
1231
- canvas.addEventListener("mousedown", this._canvasMouseDownListener = (e) => {
1232
- e.preventDefault();
1233
- if (!this._visible) {
1234
- return;
1235
- }
1236
- if (!grabbed) {
1237
- return;
1238
- }
1239
- this._viewer.cameraControl.pointerEnabled = false;
1240
- switch (e.which) {
1241
- case 1: // Left button
1242
- mouseDownLeft = true;
1243
- down = true;
1244
- var canvasPos = getClickCoordsWithinElement(e);
1245
- dragAction = nextDragAction;
1246
- lastCanvasPos[0] = canvasPos[0];
1247
- lastCanvasPos[1] = canvasPos[1];
1248
- break;
1249
-
1250
- default:
1251
- break;
558
+ addCanvasEventListener("mouseup", (e) => {
559
+ if (currentDrag) {
560
+ currentDrag.onChange(e);
561
+ currentDrag.cleanup();
1252
562
  }
1253
563
  });
1254
564
 
1255
- canvas.addEventListener("mousemove", this._canvasMouseMoveListener = (e) => {
1256
- if (!this._visible) {
1257
- return;
1258
- }
1259
- if (!down) {
1260
- return;
1261
- }
1262
- var canvasPos = getClickCoordsWithinElement(e);
1263
- const x = canvasPos[0];
1264
- const y = canvasPos[1];
1265
-
1266
- switch (dragAction) {
1267
- case DRAG_ACTIONS.xTranslate:
1268
- dragTranslateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);
1269
- break;
1270
- case DRAG_ACTIONS.yTranslate:
1271
- dragTranslateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);
1272
- break;
1273
- case DRAG_ACTIONS.zTranslate:
1274
- dragTranslateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);
1275
- break;
1276
- case DRAG_ACTIONS.xRotate:
1277
- dragRotateSectionPlane(xBaseAxis, lastCanvasPos, canvasPos);
1278
- break;
1279
- case DRAG_ACTIONS.yRotate:
1280
- dragRotateSectionPlane(yBaseAxis, lastCanvasPos, canvasPos);
1281
- break;
1282
- case DRAG_ACTIONS.zRotate:
1283
- dragRotateSectionPlane(zBaseAxis, lastCanvasPos, canvasPos);
1284
- break;
565
+
566
+ addCanvasEventListener("touchstart", event => {
567
+ event.preventDefault();
568
+ if (event.touches.length === 1)
569
+ {
570
+ const touchStartId = event.touches[0].identifier;
571
+ startDrag(event, event => [...event.changedTouches].find(e => e.identifier === touchStartId));
1285
572
  }
573
+ });
1286
574
 
1287
- lastCanvasPos[0] = x;
1288
- lastCanvasPos[1] = y;
575
+ addCanvasEventListener("touchmove", event => {
576
+ event.preventDefault();
577
+ currentDrag && currentDrag.onChange(event);
1289
578
  });
1290
579
 
1291
- canvas.addEventListener("mouseup", this._canvasMouseUpListener = (e) => {
1292
- if (!this._visible) {
1293
- return;
1294
- }
1295
- this._viewer.cameraControl.pointerEnabled = true;
1296
- if (!down) {
1297
- return;
580
+ addCanvasEventListener("touchend", event => {
581
+ event.preventDefault();
582
+ if (currentDrag) {
583
+ currentDrag.onChange(event);
584
+ currentDrag.cleanup();
1298
585
  }
1299
- switch (e.which) {
1300
- case 1: // Left button
1301
- mouseDownLeft = false;
1302
- break;
1303
- case 2: // Middle/both buttons
1304
- mouseDownMiddle = false;
1305
- break;
1306
- case 3: // Right button
1307
- mouseDownRight = false;
1308
- break;
1309
- default:
1310
- break;
1311
- }
1312
- down = false;
1313
- grabbed = false;
1314
586
  });
587
+ }
1315
588
 
1316
- canvas.addEventListener("wheel", this._canvasWheelListener = (e) => {
1317
- if (!this._visible) {
1318
- return;
1319
- }
1320
- var delta = Math.max(-1, Math.min(1, -e.deltaY * 40));
1321
- if (delta === 0) {
1322
- return;
589
+ this._unbindSectionPlane = () => { };
590
+
591
+ this.__setSectionPlane = sectionPlane => {
592
+ this.id = sectionPlane.id;
593
+ this._sectionPlane = sectionPlane;
594
+ const setPosFromSectionPlane = () => setPos(sectionPlane.pos);
595
+ const setDirFromSectionPlane = () => rootNode.quaternion = math.vec3PairToQuaternion(zeroVec, sectionPlane.dir, quat);
596
+ setPosFromSectionPlane();
597
+ setDirFromSectionPlane();
598
+ const onSectionPlanePos = sectionPlane.on("pos", setPosFromSectionPlane);
599
+ const onSectionPlaneDir = sectionPlane.on("dir", () => {
600
+ if (!ignoreNextSectionPlaneDirUpdate) {
601
+ setDirFromSectionPlane();
602
+ } else {
603
+ ignoreNextSectionPlaneDirUpdate = false;
1323
604
  }
1324
605
  });
1325
- }
606
+
607
+ this._unbindSectionPlane = () => {
608
+ this.id = null;
609
+ this._sectionPlane = null;
610
+ sectionPlane.off(onSectionPlanePos);
611
+ sectionPlane.off(onSectionPlaneDir);
612
+ this._unbindSectionPlane = () => { };
613
+ };
614
+ };
615
+
616
+ this.__destroy = () => {
617
+ cleanups.forEach(c => c());
618
+ this._unbindSectionPlane();
619
+ rootNode.destroy();
620
+ this._displayMeshes = [ ];
621
+ for (let id in handlers) {
622
+ delete handlers[id];
623
+ }
624
+ };
1326
625
  }
1327
626
 
1328
627
  _destroy() {
1329
- this._unbindEvents();
1330
- this._destroyNodes();
628
+ this.__destroy();
1331
629
  }
1332
630
 
1333
- _unbindEvents() {
1334
-
1335
- const viewer = this._viewer;
1336
- const scene = viewer.scene;
1337
- const canvas = scene.canvas.canvas;
1338
- const camera = viewer.camera;
1339
- const cameraControl = viewer.cameraControl;
1340
-
1341
- scene.off(this._onSceneTick);
631
+ /**
632
+ * Called by SectionPlanesPlugin to assign this Control to a SectionPlane.
633
+ * SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.
634
+ * Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.
635
+ * @private
636
+ */
637
+ _setSectionPlane(sectionPlane) {
638
+ this._unbindSectionPlane();
639
+ if (sectionPlane) {
640
+ this.__setSectionPlane(sectionPlane);
641
+ }
642
+ }
1342
643
 
1343
- canvas.removeEventListener("mousedown", this._canvasMouseDownListener);
1344
- canvas.removeEventListener("mousemove", this._canvasMouseMoveListener);
1345
- canvas.removeEventListener("mouseup", this._canvasMouseUpListener);
1346
- canvas.removeEventListener("wheel", this._canvasWheelListener);
644
+ /**
645
+ * Gets the {@link SectionPlane} controlled by this Control.
646
+ * @returns {SectionPlane} The SectionPlane.
647
+ */
648
+ get sectionPlane() {
649
+ return this._sectionPlane;
650
+ }
1347
651
 
1348
- camera.off(this._onCameraViewMatrix);
1349
- camera.off(this._onCameraProjMatrix);
652
+ /**
653
+ * Sets if this Control is visible.
654
+ *
655
+ * @type {Boolean}
656
+ */
657
+ setVisible(visible = true) {
658
+ if (this._visible !== visible) {
659
+ this._visible = visible;
660
+ this._displayMeshes.forEach(m => m.visible = visible);
661
+ }
662
+ }
1350
663
 
1351
- cameraControl.off(this._onCameraControlHover);
1352
- cameraControl.off(this._onCameraControlHoverLeave);
664
+ /**
665
+ * Gets if this Control is visible.
666
+ *
667
+ * @type {Boolean}
668
+ */
669
+ getVisible() {
670
+ return this._visible;
1353
671
  }
1354
672
 
1355
- _destroyNodes() {
1356
- this._setSectionPlane(null);
1357
- this._rootNode.destroy();
1358
- this._displayMeshes = {};
1359
- this._affordanceMeshes = {};
673
+ /**
674
+ * Sets if this Control is culled. This is called by SectionPlanesPlugin to
675
+ * temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().
676
+ * @param culled
677
+ */
678
+ setCulled(culled) {
679
+ this._displayMeshes.forEach(m => m.culled = culled);
1360
680
  }
1361
681
  }
1362
682
 
1363
- export {Control};
683
+ export {Control};