@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.
- package/dist/xeokit-sdk.cjs.js +592 -1237
- package/dist/xeokit-sdk.es.js +592 -1237
- package/dist/xeokit-sdk.es5.js +155 -197
- 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/extras/PointerLens/PointerLens.js +27 -46
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +29 -20
- package/src/plugins/AnnotationsPlugin/Annotation.js +3 -0
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +27 -33
- package/src/plugins/SectionPlanesPlugin/Control.js +462 -1142
- package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +10 -4
- package/src/plugins/lib/html/MenuEvent.js +3 -1
- package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +1 -2
- package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +1 -1
- package/types/plugins/AngleMeasurementsPlugin/index.d.ts +2 -1
- package/types/plugins/CityJSONLoaderPlugin/CityJSONLoaderPlugin.d.ts +4 -0
- package/types/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.d.ts +121 -0
- package/types/plugins/DotBIMLoaderPlugin/index.d.ts +1 -0
- package/types/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.d.ts +4 -0
- package/types/plugins/LASLoaderPlugin/LASLoaderPlugin.d.ts +4 -0
- package/types/plugins/STLLoaderPlugin/STLLoaderPlugin.d.ts +4 -0
- package/types/plugins/TreeViewPlugin/TreeViewPlugin.d.ts +4 -0
- package/types/plugins/WebIFCLoaderPlugin/WebIFCLoaderPlugin.d.ts +4 -0
- package/types/plugins/XKTLoaderPlugin/XKTLoaderPlugin.d.ts +19 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
|
182
|
-
const
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
-
|
|
104
|
+
arrowHead: arrowGeometry(0.07, 0.2),
|
|
105
|
+
arrowHeadBig: arrowGeometry(0.09, 0.25),
|
|
106
|
+
arrowHeadHandle: tubeGeometry(handleRadius, 0.37, 8),
|
|
351
107
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
|
|
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
|
-
|
|
152
|
+
const curve = rootNode.addChild(new Mesh(rootNode, {
|
|
491
153
|
geometry: shapes.curve,
|
|
492
|
-
material:
|
|
493
|
-
|
|
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
|
-
|
|
164
|
+
const rotateHandle = rootNode.addChild(new Mesh(rootNode, {
|
|
503
165
|
geometry: shapes.curveHandle,
|
|
504
|
-
material:
|
|
505
|
-
|
|
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
|
-
|
|
176
|
+
const arrow1 = rootNode.addChild(new Mesh(rootNode, {
|
|
515
177
|
geometry: shapes.arrowHead,
|
|
516
|
-
material:
|
|
517
|
-
matrix: (
|
|
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
|
-
|
|
187
|
+
const arrow2 = rootNode.addChild(new Mesh(rootNode, {
|
|
531
188
|
geometry: shapes.arrowHead,
|
|
532
|
-
material:
|
|
533
|
-
matrix: (
|
|
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
|
-
|
|
551
|
-
|
|
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
|
-
|
|
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
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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
|
-
|
|
218
|
+
const arrow = rootNode.addChild(new Mesh(rootNode, {
|
|
688
219
|
geometry: shapes.arrowHead,
|
|
689
|
-
material:
|
|
690
|
-
matrix:
|
|
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
|
-
|
|
229
|
+
const arrowHandle = rootNode.addChild(new Mesh(rootNode, {
|
|
703
230
|
geometry: shapes.arrowHeadHandle,
|
|
704
|
-
material:
|
|
705
|
-
matrix:
|
|
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
|
-
|
|
240
|
+
const shaft = rootNode.addChild(new Mesh(rootNode, {
|
|
719
241
|
geometry: shapes.axis,
|
|
720
|
-
material:
|
|
721
|
-
|
|
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
|
-
|
|
251
|
+
const shaftHandle = rootNode.addChild(new Mesh(rootNode, {
|
|
730
252
|
geometry: shapes.axisHandle,
|
|
731
|
-
material:
|
|
732
|
-
|
|
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
|
-
|
|
745
|
-
geometry: shapes.
|
|
746
|
-
material:
|
|
747
|
-
matrix:
|
|
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
|
-
|
|
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
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
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
|
-
|
|
401
|
+
rootNode.addChild(new Mesh(rootNode, { // Visible frame
|
|
809
402
|
geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
|
|
810
403
|
center: [0, 0, 0],
|
|
811
|
-
radius:
|
|
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
|
-
|
|
411
|
+
emissive: [0, 0, 0],
|
|
819
412
|
diffuse: [0, 0, 0],
|
|
820
|
-
|
|
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: [
|
|
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
|
-
|
|
839
|
-
geometry:
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
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
|
-
|
|
913
|
-
|
|
914
|
-
|
|
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
|
-
|
|
952
|
-
|
|
953
|
-
|
|
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
|
|
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
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
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
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
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
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
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
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
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
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
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
|
-
|
|
1127
|
-
}
|
|
1128
|
-
})();
|
|
527
|
+
};
|
|
1129
528
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
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
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
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
|
-
|
|
1221
|
-
if (
|
|
1222
|
-
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
|
|
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
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
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
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
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
|
-
|
|
1288
|
-
|
|
575
|
+
addCanvasEventListener("touchmove", event => {
|
|
576
|
+
event.preventDefault();
|
|
577
|
+
currentDrag && currentDrag.onChange(event);
|
|
1289
578
|
});
|
|
1290
579
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
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
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
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.
|
|
1330
|
-
this._destroyNodes();
|
|
628
|
+
this.__destroy();
|
|
1331
629
|
}
|
|
1332
630
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
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
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
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
|
-
|
|
1349
|
-
|
|
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
|
-
|
|
1352
|
-
|
|
664
|
+
/**
|
|
665
|
+
* Gets if this Control is visible.
|
|
666
|
+
*
|
|
667
|
+
* @type {Boolean}
|
|
668
|
+
*/
|
|
669
|
+
getVisible() {
|
|
670
|
+
return this._visible;
|
|
1353
671
|
}
|
|
1354
672
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
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};
|