@xeokit/xeokit-sdk 2.6.63 → 2.6.64
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 +506 -1069
- package/dist/xeokit-sdk.es.js +506 -1069
- package/dist/xeokit-sdk.es5.js +120 -151
- package/dist/xeokit-sdk.min.cjs.js +4 -4
- package/dist/xeokit-sdk.min.es.js +2 -2
- package/dist/xeokit-sdk.min.es5.js +3 -3
- package/package.json +1 -1
- package/src/plugins/SectionPlanesPlugin/Control.js +527 -1118
|
@@ -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,1045 +35,476 @@ 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
45
|
|
|
44
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
})(),
|
|
523
|
-
pickable: true,
|
|
524
|
-
collidable: true,
|
|
525
|
-
clippable: false,
|
|
526
|
-
visible: false,
|
|
527
|
-
isObject: false
|
|
528
|
-
}), NO_STATE_INHERIT),
|
|
529
|
-
|
|
530
|
-
yCurveArrow2: rootNode.addChild(new Mesh(rootNode, {
|
|
531
|
-
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
|
-
})(),
|
|
539
|
-
pickable: true,
|
|
540
|
-
collidable: true,
|
|
541
|
-
clippable: false,
|
|
542
|
-
visible: false,
|
|
543
|
-
isObject: false
|
|
544
|
-
}), NO_STATE_INHERIT),
|
|
545
|
-
|
|
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
|
-
})(),
|
|
631
|
-
pickable: false,
|
|
632
|
-
collidable: true,
|
|
633
|
-
clippable: false,
|
|
634
|
-
visible: false,
|
|
635
|
-
isObject: false
|
|
636
|
-
}), NO_STATE_INHERIT),
|
|
637
|
-
|
|
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
|
-
|
|
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),
|
|
667
|
-
|
|
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
|
-
})(),
|
|
178
|
+
material: material,
|
|
179
|
+
matrix: scaledArrowMatrix([ .8, .07, 0 ], math.rotationMat4v(180 * math.DEGTORAD, [0, 0, 1], math.identityMat4())),
|
|
676
180
|
pickable: true,
|
|
677
181
|
collidable: true,
|
|
678
182
|
clippable: false,
|
|
679
|
-
visible: false,
|
|
680
|
-
isObject: false
|
|
681
|
-
}), NO_STATE_INHERIT)
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
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
|
-
})(),
|
|
695
|
-
pickable: false,
|
|
696
|
-
collidable: true,
|
|
697
|
-
clippable: false,
|
|
698
|
-
visible: false,
|
|
699
|
-
isObject: false
|
|
700
|
-
}), NO_STATE_INHERIT),
|
|
701
|
-
|
|
702
|
-
yAxisArrowHandle: rootNode.addChild(new Mesh(rootNode, {
|
|
703
|
-
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
|
-
})(),
|
|
710
|
-
pickable: true,
|
|
711
|
-
collidable: true,
|
|
712
|
-
clippable: false,
|
|
713
|
-
visible: false,
|
|
714
|
-
opacity: 0.2,
|
|
715
|
-
isObject: false
|
|
716
|
-
}), NO_STATE_INHERIT),
|
|
717
|
-
|
|
718
|
-
yShaft: rootNode.addChild(new Mesh(rootNode, {
|
|
719
|
-
geometry: shapes.axis,
|
|
720
|
-
material: materials.green,
|
|
721
|
-
position: [0, -radius / 2, 0],
|
|
722
|
-
pickable: false,
|
|
723
|
-
collidable: true,
|
|
724
|
-
clippable: false,
|
|
725
|
-
visible: false,
|
|
726
|
-
isObject: false
|
|
727
|
-
}), NO_STATE_INHERIT),
|
|
728
|
-
|
|
729
|
-
yShaftHandle: rootNode.addChild(new Mesh(rootNode, {
|
|
730
|
-
geometry: shapes.axisHandle,
|
|
731
|
-
material: materials.pickable,
|
|
732
|
-
position: [0, -radius / 2, 0],
|
|
733
|
-
pickable: true,
|
|
734
|
-
collidable: true,
|
|
735
|
-
clippable: false,
|
|
736
|
-
visible: false,
|
|
737
|
-
isObject: false
|
|
738
|
-
}), NO_STATE_INHERIT),
|
|
739
|
-
|
|
740
|
-
//----------------------------------------------------------------------------------------------------------
|
|
741
|
-
//
|
|
742
|
-
//----------------------------------------------------------------------------------------------------------
|
|
743
|
-
|
|
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
|
-
})(),
|
|
752
|
-
pickable: false,
|
|
753
|
-
collidable: true,
|
|
754
|
-
clippable: false,
|
|
755
|
-
visible: false,
|
|
756
|
-
isObject: false
|
|
757
|
-
}), NO_STATE_INHERIT),
|
|
758
|
-
|
|
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),
|
|
773
|
-
|
|
774
|
-
|
|
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,
|
|
784
|
-
pickable: false,
|
|
785
|
-
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
|
-
clippable: false,
|
|
799
|
-
pickable: true,
|
|
800
|
-
collidable: true,
|
|
801
|
-
visible: false,
|
|
802
|
-
isObject: false
|
|
803
|
-
}), NO_STATE_INHERIT)
|
|
804
|
-
};
|
|
805
|
-
|
|
806
|
-
this._affordanceMeshes = {
|
|
807
|
-
|
|
808
|
-
planeFrame: rootNode.addChild(new Mesh(rootNode, {
|
|
809
|
-
geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
|
|
810
|
-
center: [0, 0, 0],
|
|
811
|
-
radius: 2,
|
|
812
|
-
tube: tubeRadius,
|
|
813
|
-
radialSegments: 4,
|
|
814
|
-
tubeSegments: 4,
|
|
815
|
-
arc: Math.PI * 2.0
|
|
816
|
-
})),
|
|
817
|
-
material: new PhongMaterial(rootNode, {
|
|
818
|
-
ambient: [1, 1, 1],
|
|
819
|
-
diffuse: [0, 0, 0],
|
|
820
|
-
emissive: [1, 1, 0]
|
|
821
|
-
}),
|
|
822
|
-
highlighted: true,
|
|
823
|
-
highlightMaterial: new EmphasisMaterial(rootNode, {
|
|
824
|
-
edges: false,
|
|
825
|
-
filled: true,
|
|
826
|
-
fillColor: [1, 1, 0],
|
|
827
|
-
fillAlpha: 1.0
|
|
828
|
-
}),
|
|
829
|
-
pickable: false,
|
|
830
|
-
collidable: false,
|
|
183
|
+
visible: false,
|
|
184
|
+
isObject: false
|
|
185
|
+
}), NO_STATE_INHERIT);
|
|
186
|
+
|
|
187
|
+
const arrow2 = rootNode.addChild(new Mesh(rootNode, {
|
|
188
|
+
geometry: shapes.arrowHead,
|
|
189
|
+
material: material,
|
|
190
|
+
matrix: scaledArrowMatrix([ .07, .8, 0 ], math.rotationMat4v(90 * math.DEGTORAD, [0, 0, 1], math.identityMat4())),
|
|
191
|
+
pickable: true,
|
|
192
|
+
collidable: true,
|
|
831
193
|
clippable: false,
|
|
832
194
|
visible: false,
|
|
833
|
-
scale: [1, 1, 1],
|
|
834
|
-
rotation: [0, 0, 45],
|
|
835
195
|
isObject: false
|
|
836
|
-
}), NO_STATE_INHERIT)
|
|
196
|
+
}), NO_STATE_INHERIT);
|
|
837
197
|
|
|
838
|
-
|
|
198
|
+
const hoop = rootNode.addChild(new Mesh(rootNode, {
|
|
839
199
|
geometry: shapes.hoop,
|
|
840
|
-
material:
|
|
200
|
+
material: material,
|
|
841
201
|
highlighted: true,
|
|
842
|
-
highlightMaterial:
|
|
843
|
-
matrix:
|
|
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
|
-
})(),
|
|
202
|
+
highlightMaterial: highlightMaterial(rgb, 0.6),
|
|
203
|
+
matrix: hoopMatrix,
|
|
848
204
|
pickable: false,
|
|
849
205
|
collidable: true,
|
|
850
206
|
clippable: false,
|
|
851
207
|
visible: false,
|
|
852
208
|
isObject: false
|
|
853
|
-
}), NO_STATE_INHERIT)
|
|
209
|
+
}), NO_STATE_INHERIT);
|
|
854
210
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
211
|
+
|
|
212
|
+
const axisRotation = math.quaternionToRotationMat4(math.vec3PairToQuaternion([ 0, 1, 0 ], axisDirection), math.identityMat4());
|
|
213
|
+
|
|
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);
|
|
217
|
+
|
|
218
|
+
const arrow = rootNode.addChild(new Mesh(rootNode, {
|
|
219
|
+
geometry: shapes.arrowHead,
|
|
220
|
+
material: material,
|
|
221
|
+
matrix: arrowMatrix,
|
|
861
222
|
pickable: false,
|
|
862
223
|
collidable: true,
|
|
863
224
|
clippable: false,
|
|
864
225
|
visible: false,
|
|
865
226
|
isObject: false
|
|
866
|
-
}), NO_STATE_INHERIT)
|
|
227
|
+
}), NO_STATE_INHERIT);
|
|
867
228
|
|
|
868
|
-
|
|
869
|
-
geometry: shapes.
|
|
870
|
-
material:
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
matrix: math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4()),
|
|
874
|
-
pickable: false,
|
|
229
|
+
const arrowHandle = rootNode.addChild(new Mesh(rootNode, {
|
|
230
|
+
geometry: shapes.arrowHeadHandle,
|
|
231
|
+
material: pickableMaterial,
|
|
232
|
+
matrix: arrowMatrix,
|
|
233
|
+
pickable: true,
|
|
875
234
|
collidable: true,
|
|
876
235
|
clippable: false,
|
|
877
|
-
backfaces: true,
|
|
878
236
|
visible: false,
|
|
879
237
|
isObject: false
|
|
880
|
-
}), NO_STATE_INHERIT)
|
|
238
|
+
}), NO_STATE_INHERIT);
|
|
881
239
|
|
|
882
|
-
|
|
883
|
-
geometry: shapes.
|
|
884
|
-
material:
|
|
885
|
-
matrix:
|
|
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
|
-
})(),
|
|
240
|
+
const shaft = rootNode.addChild(new Mesh(rootNode, {
|
|
241
|
+
geometry: shapes.axis,
|
|
242
|
+
material: material,
|
|
243
|
+
matrix: shaftMatrix,
|
|
890
244
|
pickable: false,
|
|
891
245
|
collidable: true,
|
|
892
246
|
clippable: false,
|
|
893
247
|
visible: false,
|
|
894
248
|
isObject: false
|
|
895
|
-
}), NO_STATE_INHERIT)
|
|
249
|
+
}), NO_STATE_INHERIT);
|
|
896
250
|
|
|
897
|
-
|
|
898
|
-
geometry: shapes.
|
|
899
|
-
material:
|
|
900
|
-
matrix:
|
|
901
|
-
|
|
902
|
-
const rotate = math.rotationMat4v(180 * math.DEGTORAD, [1, 0, 0], math.identityMat4());
|
|
903
|
-
return math.mulMat4(rotate, translate, math.identityMat4());
|
|
904
|
-
})(),
|
|
905
|
-
pickable: false,
|
|
251
|
+
const shaftHandle = rootNode.addChild(new Mesh(rootNode, {
|
|
252
|
+
geometry: shapes.axisHandle,
|
|
253
|
+
material: pickableMaterial,
|
|
254
|
+
matrix: shaftMatrix,
|
|
255
|
+
pickable: true,
|
|
906
256
|
collidable: true,
|
|
907
257
|
clippable: false,
|
|
908
258
|
visible: false,
|
|
909
259
|
isObject: false
|
|
910
|
-
}), NO_STATE_INHERIT)
|
|
260
|
+
}), NO_STATE_INHERIT);
|
|
911
261
|
|
|
912
|
-
|
|
262
|
+
const bigArrowHead = rootNode.addChild(new Mesh(rootNode, {
|
|
913
263
|
geometry: shapes.arrowHeadBig,
|
|
914
|
-
material:
|
|
915
|
-
matrix:
|
|
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
|
-
})(),
|
|
264
|
+
material: material,
|
|
265
|
+
matrix: arrowMatrix,
|
|
920
266
|
pickable: false,
|
|
921
267
|
collidable: true,
|
|
922
268
|
clippable: false,
|
|
923
269
|
visible: false,
|
|
924
270
|
isObject: false
|
|
925
|
-
}), NO_STATE_INHERIT)
|
|
926
|
-
};
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
_bindEvents() {
|
|
930
|
-
|
|
931
|
-
const self = this;
|
|
271
|
+
}), NO_STATE_INHERIT);
|
|
932
272
|
|
|
933
|
-
|
|
273
|
+
const closestPointOnAxis = (function() {
|
|
274
|
+
const worldAxis = math.vec4();
|
|
275
|
+
const org = math.vec3();
|
|
276
|
+
const dir = math.vec3();
|
|
277
|
+
return (canvasPos, dst) => {
|
|
278
|
+
localToWorldVec(rgb, worldAxis);
|
|
934
279
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
xTranslate: 0,
|
|
938
|
-
yTranslate: 1,
|
|
939
|
-
zTranslate: 2,
|
|
940
|
-
xRotate: 3,
|
|
941
|
-
yRotate: 4,
|
|
942
|
-
zRotate: 5
|
|
943
|
-
};
|
|
280
|
+
const P = pos;
|
|
281
|
+
const D = worldAxis;
|
|
944
282
|
|
|
945
|
-
|
|
283
|
+
math.canvasPosToWorldRay(canvas, scene.camera.viewMatrix, scene.camera.projMatrix, scene.camera.projection, canvasPos, org, dir);
|
|
946
284
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
285
|
+
const d01 = math.dotVec3(D, dir);
|
|
286
|
+
const v = math.subVec3(org, P, dst);
|
|
287
|
+
const v0 = math.dotVec3(v, D);
|
|
288
|
+
const v1 = math.dotVec3(v, dir);
|
|
289
|
+
const det = 1 - d01 * d01;
|
|
950
290
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
291
|
+
if (Math.abs(det) > 1e-10) { // if lines are not parallel
|
|
292
|
+
const s = (v0 - d01 * v1) / det;
|
|
293
|
+
math.addVec3(P, math.mulVec3Scalar(D, s, dst), dst);
|
|
294
|
+
return true;
|
|
295
|
+
} else {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
})();
|
|
300
|
+
const initOffset = math.vec3();
|
|
301
|
+
const tempVec3 = math.vec3();
|
|
302
|
+
handlers[arrowHandle.id] = handlers[shaftHandle.id] = {
|
|
303
|
+
setActivated: a => bigArrowHead.visible = a,
|
|
304
|
+
initDragAction: (initCanvasPos) => {
|
|
305
|
+
return closestPointOnAxis(initCanvasPos, initOffset) && math.subVec3(initOffset, pos, initOffset) && ((canvasPos) => {
|
|
306
|
+
if (closestPointOnAxis(canvasPos, tempVec3)) {
|
|
307
|
+
math.subVec3(tempVec3, initOffset, tempVec3);
|
|
308
|
+
setPos(tempVec3);
|
|
309
|
+
if (self._sectionPlane) {
|
|
310
|
+
self._sectionPlane.pos = tempVec3;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
};
|
|
954
316
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
317
|
+
const lastCanvasPos = math.vec2();
|
|
318
|
+
handlers[rotateHandle.id] = {
|
|
319
|
+
setActivated: a => hoop.visible = a,
|
|
320
|
+
initDragAction: (initCanvasPos) => {
|
|
321
|
+
lastCanvasPos.set(initCanvasPos);
|
|
322
|
+
return canvasPos => {
|
|
323
|
+
dragRotateSectionPlane(rgb, lastCanvasPos, canvasPos);
|
|
324
|
+
lastCanvasPos.set(canvasPos);
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
};
|
|
958
328
|
|
|
959
|
-
|
|
329
|
+
return {
|
|
330
|
+
set visible(v) {
|
|
331
|
+
arrow.visible = arrowHandle.visible = shaft.visible = shaftHandle.visible = curve.visible = rotateHandle.visible = arrow1.visible = arrow2.visible = v;
|
|
332
|
+
if (! v) {
|
|
333
|
+
bigArrowHead.visible = v;
|
|
334
|
+
hoop.visible = v;
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
set culled(c) {
|
|
338
|
+
arrow.culled = arrowHandle.culled = shaft.culled = shaftHandle.culled = curve.culled = rotateHandle.culled = arrow1.culled = arrow2.culled = c;
|
|
339
|
+
if (! c) {
|
|
340
|
+
bigArrowHead.culled = c;
|
|
341
|
+
hoop.culled = c;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
};
|
|
960
346
|
|
|
961
|
-
|
|
347
|
+
this._displayMeshes = [ // Meshes that are always visible
|
|
348
|
+
rootNode.addChild(new Mesh(rootNode, { // plane
|
|
349
|
+
geometry: new ReadableGeometry(rootNode, {
|
|
350
|
+
primitive: "triangles",
|
|
351
|
+
positions: [
|
|
352
|
+
0.5, 0.5, 0.0, 0.5, -0.5, 0.0, // 0
|
|
353
|
+
-0.5, -0.5, 0.0, -0.5, 0.5, 0.0, // 1
|
|
354
|
+
0.5, 0.5, -0.0, 0.5, -0.5, -0.0, // 2
|
|
355
|
+
-0.5, -0.5, -0.0, -0.5, 0.5, -0.0 // 3
|
|
356
|
+
],
|
|
357
|
+
indices: [0, 1, 2, 2, 3, 0]
|
|
358
|
+
}),
|
|
359
|
+
material: new PhongMaterial(rootNode, {
|
|
360
|
+
emissive: [0, 0.0, 0],
|
|
361
|
+
diffuse: [0, 0, 0],
|
|
362
|
+
backfaces: true
|
|
363
|
+
}),
|
|
364
|
+
opacity: 0.6,
|
|
365
|
+
ghosted: true,
|
|
366
|
+
ghostMaterial: new EmphasisMaterial(rootNode, {
|
|
367
|
+
edges: false,
|
|
368
|
+
filled: true,
|
|
369
|
+
fillColor: [1, 1, 0],
|
|
370
|
+
edgeColor: [0, 0, 0],
|
|
371
|
+
fillAlpha: 0.1,
|
|
372
|
+
backfaces: true
|
|
373
|
+
}),
|
|
374
|
+
pickable: false,
|
|
375
|
+
collidable: true,
|
|
376
|
+
clippable: false,
|
|
377
|
+
visible: false,
|
|
378
|
+
scale: [2.4, 2.4, 1],
|
|
379
|
+
isObject: false
|
|
380
|
+
}), NO_STATE_INHERIT),
|
|
962
381
|
|
|
963
|
-
|
|
964
|
-
|
|
382
|
+
rootNode.addChild(new Mesh(rootNode, { // Visible frame
|
|
383
|
+
geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
|
|
384
|
+
center: [0, 0, 0],
|
|
385
|
+
radius: 1.7,
|
|
386
|
+
tube: tubeRadius * 2,
|
|
387
|
+
radialSegments: 4,
|
|
388
|
+
tubeSegments: 4,
|
|
389
|
+
arc: Math.PI * 2.0
|
|
390
|
+
})),
|
|
391
|
+
material: new PhongMaterial(rootNode, {
|
|
392
|
+
emissive: [0, 0, 0],
|
|
393
|
+
diffuse: [0, 0, 0],
|
|
394
|
+
specular: [0, 0, 0],
|
|
395
|
+
shininess: 0
|
|
396
|
+
}),
|
|
397
|
+
//highlighted: true,
|
|
398
|
+
highlightMaterial: new EmphasisMaterial(rootNode, {
|
|
399
|
+
edges: false,
|
|
400
|
+
edgeColor: [0.0, 0.0, 0.0],
|
|
401
|
+
filled: true,
|
|
402
|
+
fillColor: [0.8, 0.8, 0.8],
|
|
403
|
+
fillAlpha: 1.0
|
|
404
|
+
}),
|
|
405
|
+
pickable: false,
|
|
406
|
+
collidable: false,
|
|
407
|
+
clippable: false,
|
|
408
|
+
visible: false,
|
|
409
|
+
scale: [1, 1, .1],
|
|
410
|
+
rotation: [0, 0, 45],
|
|
411
|
+
isObject: false
|
|
412
|
+
}), NO_STATE_INHERIT),
|
|
965
413
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
414
|
+
rootNode.addChild(new Mesh(rootNode, { // center
|
|
415
|
+
geometry: new ReadableGeometry(rootNode, buildSphereGeometry({
|
|
416
|
+
radius: 0.05
|
|
417
|
+
})),
|
|
418
|
+
material: new PhongMaterial(rootNode, {
|
|
419
|
+
diffuse: [0.0, 0.0, 0.0],
|
|
420
|
+
emissive: [0, 0, 0],
|
|
421
|
+
ambient: [0.0, 0.0, 0.0],
|
|
422
|
+
specular: [.6, .6, .3],
|
|
423
|
+
shininess: 80
|
|
424
|
+
}),
|
|
425
|
+
pickable: false,
|
|
426
|
+
collidable: true,
|
|
427
|
+
clippable: false,
|
|
428
|
+
visible: false,
|
|
429
|
+
isObject: false
|
|
430
|
+
}), NO_STATE_INHERIT),
|
|
969
431
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
432
|
+
//----------------------------------------------------------------------------------------------------------
|
|
433
|
+
//
|
|
434
|
+
//----------------------------------------------------------------------------------------------------------
|
|
973
435
|
|
|
974
|
-
|
|
436
|
+
addAxis([1,0,0], [ 1, 0, 0 ], [ 1, 0, 0 ]),
|
|
437
|
+
addAxis([0,1,0], [ 0, -1, 0 ], [ 0, 1, 0 ]),
|
|
438
|
+
addAxis([0,0,1], [ 0, 0, -1 ], [ 0, 0, -1 ])
|
|
439
|
+
];
|
|
975
440
|
|
|
976
|
-
|
|
441
|
+
const cleanups = [ ];
|
|
977
442
|
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
443
|
+
{ // Keep gizmo screen size constant
|
|
444
|
+
let lastDist = -1;
|
|
445
|
+
const setRootNodeScale = size => rootNode.scale = [size, size, size];
|
|
446
|
+
const onSceneTick = scene.on("tick", () => {
|
|
447
|
+
const dist = Math.abs(math.distVec3(camera.eye, pos));
|
|
448
|
+
if (camera.projection === "perspective") {
|
|
449
|
+
if (dist !== lastDist) {
|
|
450
|
+
setRootNodeScale(0.07 * dist * Math.tan(camera.perspective.fov * math.DEGTORAD));
|
|
984
451
|
}
|
|
452
|
+
} else if (camera.projection === "ortho") {
|
|
453
|
+
setRootNodeScale(camera.ortho.scale / 10);
|
|
985
454
|
}
|
|
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
|
-
}
|
|
455
|
+
lastDist = dist;
|
|
993
456
|
});
|
|
457
|
+
cleanups.push(() => scene.off(onSceneTick));
|
|
994
458
|
}
|
|
995
459
|
|
|
996
|
-
const getClickCoordsWithinElement = (
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
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;
|
|
1017
|
-
};
|
|
1018
|
-
})();
|
|
460
|
+
const getClickCoordsWithinElement = (event, canvasPos) => {
|
|
461
|
+
if (!event) {
|
|
462
|
+
event = window.event;
|
|
463
|
+
canvasPos[0] = event.x;
|
|
464
|
+
canvasPos[1] = event.y;
|
|
465
|
+
} else {
|
|
466
|
+
const element = event.target;
|
|
467
|
+
const rect = element.getBoundingClientRect();
|
|
468
|
+
canvasPos[0] = event.clientX - rect.left;
|
|
469
|
+
canvasPos[1] = event.clientY - rect.top;
|
|
470
|
+
}
|
|
471
|
+
};
|
|
1019
472
|
|
|
1020
473
|
const localToWorldVec = (function () {
|
|
1021
474
|
const mat = math.mat4();
|
|
1022
475
|
return function (localVec, worldVec) {
|
|
1023
|
-
math.quaternionToMat4(
|
|
476
|
+
math.quaternionToMat4(rootNode.quaternion, mat);
|
|
1024
477
|
math.transformVec3(mat, localVec, worldVec);
|
|
1025
478
|
math.normalizeVec3(worldVec);
|
|
1026
479
|
return worldVec;
|
|
1027
480
|
};
|
|
1028
481
|
})();
|
|
1029
482
|
|
|
1030
|
-
|
|
1031
|
-
const
|
|
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
|
-
}
|
|
483
|
+
const getTranslationPlane = (worldAxis, planeNormal) => {
|
|
484
|
+
const absX = Math.abs(worldAxis[0]);
|
|
485
|
+
if (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {
|
|
486
|
+
math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);
|
|
487
|
+
} else {
|
|
488
|
+
math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);
|
|
1063
489
|
}
|
|
1064
|
-
|
|
490
|
+
math.cross3Vec3(planeNormal, worldAxis, planeNormal);
|
|
491
|
+
math.normalizeVec3(planeNormal);
|
|
492
|
+
};
|
|
1065
493
|
|
|
494
|
+
const self = this;
|
|
1066
495
|
var dragRotateSectionPlane = (function () {
|
|
1067
496
|
const p1 = math.vec4();
|
|
1068
497
|
const p2 = math.vec4();
|
|
1069
498
|
const c = math.vec4();
|
|
1070
499
|
const worldAxis = math.vec4();
|
|
500
|
+
const dir = math.vec3();
|
|
501
|
+
const mat = math.mat4();
|
|
502
|
+
const planeNormal = math.vec3();
|
|
1071
503
|
return function (baseAxis, fromMouse, toMouse) {
|
|
1072
504
|
localToWorldVec(baseAxis, worldAxis);
|
|
1073
505
|
const hasData = getPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);
|
|
1074
506
|
if (!hasData) { // Find intersections with view plane and project down to origin
|
|
1075
|
-
|
|
507
|
+
getTranslationPlane(worldAxis, planeNormal);
|
|
1076
508
|
getPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable
|
|
1077
509
|
getPointerPlaneIntersect(toMouse, planeNormal, p2, 1);
|
|
1078
510
|
var dot = math.dotVec3(p1, worldAxis);
|
|
@@ -1093,9 +525,15 @@ class Control {
|
|
|
1093
525
|
if (math.dotVec3(c, worldAxis) < 0.0) {
|
|
1094
526
|
incDegrees = -incDegrees;
|
|
1095
527
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
528
|
+
rootNode.rotate(baseAxis, incDegrees);
|
|
529
|
+
|
|
530
|
+
if (self._sectionPlane) {
|
|
531
|
+
math.quaternionToMat4(rootNode.quaternion, mat); // << ---
|
|
532
|
+
math.transformVec3(mat, [0, 0, 1], dir);
|
|
533
|
+
ignoreNextSectionPlaneDirUpdate = true;
|
|
534
|
+
self._sectionPlane.dir = dir;
|
|
535
|
+
}
|
|
536
|
+
};
|
|
1099
537
|
})();
|
|
1100
538
|
|
|
1101
539
|
var getPointerPlaneIntersect = (function () {
|
|
@@ -1124,240 +562,211 @@ class Control {
|
|
|
1124
562
|
return true;
|
|
1125
563
|
}
|
|
1126
564
|
return false;
|
|
1127
|
-
}
|
|
1128
|
-
})();
|
|
1129
|
-
|
|
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
|
-
}
|
|
1139
565
|
};
|
|
1140
566
|
})();
|
|
1141
567
|
|
|
1142
568
|
{
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
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
|
|
569
|
+
let deactivateActive = null;
|
|
570
|
+
let currentDrag = null;
|
|
571
|
+
cleanups.push(() => { if (currentDrag) { currentDrag.cleanup(); } });
|
|
572
|
+
const canvasPos = math.vec2();
|
|
573
|
+
|
|
574
|
+
const copyCanvasPos = (event, vec2) => {
|
|
575
|
+
vec2[0] = event.clientX;
|
|
576
|
+
vec2[1] = event.clientY;
|
|
577
|
+
transformToNode(canvas.ownerDocument.documentElement, canvas, vec2);
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
const pickHandler = (e) => {
|
|
581
|
+
copyCanvasPos(e, canvasPos);
|
|
582
|
+
const pickResult = viewer.scene.pick({ canvasPos: canvasPos });
|
|
583
|
+
const pickEntity = pickResult && pickResult.entity;
|
|
584
|
+
const pickId = pickEntity && pickEntity.id;
|
|
585
|
+
return (pickId in handlers) && handlers[pickId];
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
const startDrag = (event, matchesEvent) => {
|
|
589
|
+
const handler = pickHandler(matchesEvent(event));
|
|
590
|
+
if (handler) {
|
|
591
|
+
if (currentDrag) {
|
|
592
|
+
currentDrag.cleanup();
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const dragAction = handler.initDragAction(canvasPos);
|
|
596
|
+
if (dragAction) {
|
|
597
|
+
cameraControl.pointerEnabled = false; // or .active = false ?
|
|
598
|
+
handler.setActivated(true);
|
|
599
|
+
|
|
600
|
+
currentDrag = {
|
|
601
|
+
onChange: event => {
|
|
602
|
+
const e = matchesEvent(event);
|
|
603
|
+
if (e) {
|
|
604
|
+
copyCanvasPos(e, canvasPos);
|
|
605
|
+
dragAction(canvasPos);
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
cleanup: function() {
|
|
609
|
+
currentDrag = null;
|
|
610
|
+
cameraControl.pointerEnabled = true; // or .active = true ?
|
|
611
|
+
handler.setActivated(false);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
}
|
|
1212
615
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
const addCanvasEventListener = (type, listener) => {
|
|
619
|
+
canvas.addEventListener(type, listener);
|
|
620
|
+
cleanups.push(() => canvas.removeEventListener(type, listener));
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
addCanvasEventListener("mousedown", (e) => {
|
|
624
|
+
e.preventDefault();
|
|
625
|
+
if (e.which === 1) {
|
|
626
|
+
startDrag(e, event => (event.which === 1) && event);
|
|
1215
627
|
}
|
|
1216
|
-
lastAffordanceMesh = affordanceMesh;
|
|
1217
|
-
grabbed = true;
|
|
1218
628
|
});
|
|
1219
629
|
|
|
1220
|
-
|
|
1221
|
-
if (
|
|
1222
|
-
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
|
|
630
|
+
addCanvasEventListener("mousemove", (e) => {
|
|
631
|
+
if (currentDrag) {
|
|
632
|
+
currentDrag.onChange(e);
|
|
633
|
+
} else {
|
|
634
|
+
if (deactivateActive) {
|
|
635
|
+
deactivateActive();
|
|
636
|
+
}
|
|
637
|
+
const handler = pickHandler(e);
|
|
638
|
+
if (handler) {
|
|
639
|
+
handler.setActivated(true);
|
|
640
|
+
deactivateActive = () => handler.setActivated(false);
|
|
641
|
+
} else {
|
|
642
|
+
deactivateActive = null;
|
|
643
|
+
}
|
|
1226
644
|
}
|
|
1227
|
-
lastAffordanceMesh = null;
|
|
1228
|
-
nextDragAction = DRAG_ACTIONS.none;
|
|
1229
645
|
});
|
|
1230
646
|
|
|
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;
|
|
647
|
+
addCanvasEventListener("mouseup", (e) => {
|
|
648
|
+
if (currentDrag) {
|
|
649
|
+
currentDrag.onChange(e);
|
|
650
|
+
currentDrag.cleanup();
|
|
1252
651
|
}
|
|
1253
652
|
});
|
|
1254
653
|
|
|
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;
|
|
654
|
+
|
|
655
|
+
addCanvasEventListener("touchstart", event => {
|
|
656
|
+
event.preventDefault();
|
|
657
|
+
if (event.touches.length === 1)
|
|
658
|
+
{
|
|
659
|
+
const touchStartId = event.touches[0].identifier;
|
|
660
|
+
startDrag(event, event => [...event.changedTouches].find(e => e.identifier === touchStartId));
|
|
1285
661
|
}
|
|
662
|
+
});
|
|
1286
663
|
|
|
1287
|
-
|
|
1288
|
-
|
|
664
|
+
addCanvasEventListener("touchmove", event => {
|
|
665
|
+
event.preventDefault();
|
|
666
|
+
currentDrag && currentDrag.onChange(event);
|
|
1289
667
|
});
|
|
1290
668
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
if (!down) {
|
|
1297
|
-
return;
|
|
669
|
+
addCanvasEventListener("touchend", event => {
|
|
670
|
+
event.preventDefault();
|
|
671
|
+
if (currentDrag) {
|
|
672
|
+
currentDrag.onChange(event);
|
|
673
|
+
currentDrag.cleanup();
|
|
1298
674
|
}
|
|
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
675
|
});
|
|
676
|
+
}
|
|
1315
677
|
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
678
|
+
this._unbindSectionPlane = () => { };
|
|
679
|
+
|
|
680
|
+
this.__setSectionPlane = sectionPlane => {
|
|
681
|
+
this.id = sectionPlane.id;
|
|
682
|
+
this._sectionPlane = sectionPlane;
|
|
683
|
+
const setPosFromSectionPlane = () => setPos(sectionPlane.pos);
|
|
684
|
+
const setDirFromSectionPlane = () => rootNode.quaternion = math.vec3PairToQuaternion(zeroVec, sectionPlane.dir, quat);
|
|
685
|
+
setPosFromSectionPlane();
|
|
686
|
+
setDirFromSectionPlane();
|
|
687
|
+
const onSectionPlanePos = sectionPlane.on("pos", setPosFromSectionPlane);
|
|
688
|
+
const onSectionPlaneDir = sectionPlane.on("dir", () => {
|
|
689
|
+
if (!ignoreNextSectionPlaneDirUpdate) {
|
|
690
|
+
setDirFromSectionPlane();
|
|
691
|
+
} else {
|
|
692
|
+
ignoreNextSectionPlaneDirUpdate = false;
|
|
1323
693
|
}
|
|
1324
694
|
});
|
|
1325
|
-
|
|
695
|
+
|
|
696
|
+
this._unbindSectionPlane = () => {
|
|
697
|
+
this.id = null;
|
|
698
|
+
this._sectionPlane = null;
|
|
699
|
+
sectionPlane.off(onSectionPlanePos);
|
|
700
|
+
sectionPlane.off(onSectionPlaneDir);
|
|
701
|
+
this._unbindSectionPlane = () => { };
|
|
702
|
+
};
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
this.__destroy = () => {
|
|
706
|
+
cleanups.forEach(c => c());
|
|
707
|
+
this._unbindSectionPlane();
|
|
708
|
+
rootNode.destroy();
|
|
709
|
+
this._displayMeshes = [ ];
|
|
710
|
+
for (let id in handlers) {
|
|
711
|
+
delete handlers[id];
|
|
712
|
+
}
|
|
713
|
+
};
|
|
1326
714
|
}
|
|
1327
715
|
|
|
1328
716
|
_destroy() {
|
|
1329
|
-
this.
|
|
1330
|
-
this._destroyNodes();
|
|
717
|
+
this.__destroy();
|
|
1331
718
|
}
|
|
1332
719
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
720
|
+
/**
|
|
721
|
+
* Called by SectionPlanesPlugin to assign this Control to a SectionPlane.
|
|
722
|
+
* SectionPlanesPlugin keeps SectionPlaneControls in a reuse pool.
|
|
723
|
+
* Call with a null or undefined value to disconnect the Control ffrom whatever SectionPlane it was assigned to.
|
|
724
|
+
* @private
|
|
725
|
+
*/
|
|
726
|
+
_setSectionPlane(sectionPlane) {
|
|
727
|
+
this._unbindSectionPlane();
|
|
728
|
+
if (sectionPlane) {
|
|
729
|
+
this.__setSectionPlane(sectionPlane);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
1342
732
|
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
733
|
+
/**
|
|
734
|
+
* Gets the {@link SectionPlane} controlled by this Control.
|
|
735
|
+
* @returns {SectionPlane} The SectionPlane.
|
|
736
|
+
*/
|
|
737
|
+
get sectionPlane() {
|
|
738
|
+
return this._sectionPlane;
|
|
739
|
+
}
|
|
1347
740
|
|
|
1348
|
-
|
|
1349
|
-
|
|
741
|
+
/**
|
|
742
|
+
* Sets if this Control is visible.
|
|
743
|
+
*
|
|
744
|
+
* @type {Boolean}
|
|
745
|
+
*/
|
|
746
|
+
setVisible(visible = true) {
|
|
747
|
+
if (this._visible !== visible) {
|
|
748
|
+
this._visible = visible;
|
|
749
|
+
this._displayMeshes.forEach(m => m.visible = visible);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
1350
752
|
|
|
1351
|
-
|
|
1352
|
-
|
|
753
|
+
/**
|
|
754
|
+
* Gets if this Control is visible.
|
|
755
|
+
*
|
|
756
|
+
* @type {Boolean}
|
|
757
|
+
*/
|
|
758
|
+
getVisible() {
|
|
759
|
+
return this._visible;
|
|
1353
760
|
}
|
|
1354
761
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
762
|
+
/**
|
|
763
|
+
* Sets if this Control is culled. This is called by SectionPlanesPlugin to
|
|
764
|
+
* temporarily hide the Control while a snapshot is being taken by Viewer#getSnapshot().
|
|
765
|
+
* @param culled
|
|
766
|
+
*/
|
|
767
|
+
setCulled(culled) {
|
|
768
|
+
this._displayMeshes.forEach(m => m.culled = culled);
|
|
1360
769
|
}
|
|
1361
770
|
}
|
|
1362
771
|
|
|
1363
|
-
export {Control};
|
|
772
|
+
export {Control};
|