zincjs 1.0.13 → 1.0.15
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/build/zinc.frontend.js +1 -1
- package/build/zinc.js +43 -35
- package/build/zinc.js.map +1 -1
- package/package.json +3 -3
- package/src/assets/disc.png +0 -0
- package/src/assets/mapMarker.svg +11 -0
- package/src/controls.js +1594 -0
- package/src/geometryCSG.js +148 -0
- package/src/glyphsetCSG.js +84 -0
- package/src/loaders/GLTFToZincJSLoader.js +85 -0
- package/src/loaders/JSONLoader.js +697 -0
- package/src/loaders/OBJLoader.js +911 -0
- package/src/loaders/STLLoader.js +399 -0
- package/src/loaders/primitivesLoader.js +46 -0
- package/src/minimap.js +82 -0
- package/src/primitives/augmentShader.js +22 -0
- package/src/primitives/geometry.js +109 -0
- package/src/primitives/glyph.js +150 -0
- package/src/primitives/glyphset.js +657 -0
- package/src/primitives/label.js +51 -0
- package/src/primitives/lines.js +35 -0
- package/src/primitives/marker.js +88 -0
- package/src/primitives/pointset.js +53 -0
- package/src/primitives/texturePrimitive.js +16 -0
- package/src/primitives/textureSlides.js +118 -0
- package/src/primitives/zincObject.js +573 -0
- package/src/region.js +554 -0
- package/src/renderer.js +612 -0
- package/src/scene.js +963 -0
- package/src/sceneExporter.js +32 -0
- package/src/sceneLoader.js +842 -0
- package/src/texture/texture.js +57 -0
- package/src/texture/textureArray.js +85 -0
- package/src/three/GLTFExporter.js +2448 -0
- package/src/three/Geometry.js +2084 -0
- package/src/three/Loader.js +344 -0
- package/src/three/Points.js +223 -0
- package/src/three/line/Line.js +293 -0
- package/src/three/line/LineSegments.js +65 -0
- package/src/three-js-csg.js +564 -0
- package/src/utilities.js +321 -0
- package/src/videoHandler.js +92 -0
- package/src/workers/geometryCSG.worker.js +73 -0
- package/src/workers/geometryCSGInternal.js +58 -0
- package/src/zinc.js +38 -0
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
const THREE = require('three');
|
|
2
|
+
const JSONLoader = require('../loaders/JSONLoader').JSONLoader;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This is a container of {@link Zinc.Glyph} and their graphical properties
|
|
6
|
+
* including transformations, colors, number of time steps, duration of animations
|
|
7
|
+
* and group name. Please note that all glyphs in the glyphset share the same geometry
|
|
8
|
+
* however they may have different transformations.
|
|
9
|
+
*
|
|
10
|
+
* @class
|
|
11
|
+
* @author Alan Wu
|
|
12
|
+
* @return {Zinc.Glyphset}
|
|
13
|
+
*/
|
|
14
|
+
const Glyphset = function () {
|
|
15
|
+
(require('./zincObject').ZincObject).call(this);
|
|
16
|
+
const glyphList = [];
|
|
17
|
+
let axis1s = undefined;
|
|
18
|
+
let axis2s = undefined;
|
|
19
|
+
let axis3s = undefined;
|
|
20
|
+
let positions = undefined;
|
|
21
|
+
let scales = undefined;
|
|
22
|
+
let colors = undefined;
|
|
23
|
+
let labels = undefined;
|
|
24
|
+
let numberOfTimeSteps = 0;
|
|
25
|
+
let numberOfVertices = 0;
|
|
26
|
+
let baseSize = [0, 0, 0];
|
|
27
|
+
let offset = [0, 0, 0];
|
|
28
|
+
let scaleFactors = [0, 0, 0];
|
|
29
|
+
let repeat_mode = "NONE";
|
|
30
|
+
this.ready = false;
|
|
31
|
+
let morphColours = false;
|
|
32
|
+
let morphVertices = false;
|
|
33
|
+
this.isGlyphset = true;
|
|
34
|
+
let _transformMatrix = new THREE.Matrix4();
|
|
35
|
+
const _bot_colour = new THREE.Color();
|
|
36
|
+
const _top_colour = new THREE.Color();
|
|
37
|
+
const _boundingBox1 = new THREE.Box3();
|
|
38
|
+
const _boundingBox2 = new THREE.Box3();
|
|
39
|
+
const _boundingBox3 = new THREE.Box3();
|
|
40
|
+
const _points = [];
|
|
41
|
+
const _current_positions = [];
|
|
42
|
+
const _current_axis1s = [];
|
|
43
|
+
const _current_axis2s = [];
|
|
44
|
+
const _current_axis3s = [];
|
|
45
|
+
const _current_scales = [];
|
|
46
|
+
const _current_colors = [];
|
|
47
|
+
const _glyph_axis_array = [];
|
|
48
|
+
for (let i = 0; i < 8; i++) {
|
|
49
|
+
_points[i] = new THREE.Vector3();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get the {@link Three.Group} containing all of the glyphs' meshes.
|
|
54
|
+
* @returns {Three.Group}
|
|
55
|
+
*/
|
|
56
|
+
this.getGroup = () => {
|
|
57
|
+
return this.morph;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Copy glyphset data into this glyphset then load the glyph's geoemtry
|
|
62
|
+
* with the provided glyphURL. FinishCallback will be called once
|
|
63
|
+
* glyph is loaded.
|
|
64
|
+
*
|
|
65
|
+
* @param {Array} glyphsetData - contains the informations about the glyphs.
|
|
66
|
+
* @param {String} glyphURL - URL to the geometry which will be applied to all
|
|
67
|
+
* all the glyphs in the glyphset once loaded.
|
|
68
|
+
* @param {Function} finishCallback - User's function to be called once glyph's
|
|
69
|
+
* geometry is loaded.
|
|
70
|
+
*/
|
|
71
|
+
this.load = (glyphsetData, glyphURL, finishCallback, isInline, displayLabels) => {
|
|
72
|
+
axis1s = glyphsetData.axis1;
|
|
73
|
+
axis2s = glyphsetData.axis2;
|
|
74
|
+
axis3s = glyphsetData.axis3;
|
|
75
|
+
positions = glyphsetData.positions;
|
|
76
|
+
scales = glyphsetData.scale;
|
|
77
|
+
colors = glyphsetData.colors;
|
|
78
|
+
labels = glyphsetData.label;
|
|
79
|
+
morphColours = glyphsetData.metadata.MorphColours;
|
|
80
|
+
morphVertices = glyphsetData.metadata.MorphVertices;
|
|
81
|
+
numberOfTimeSteps = glyphsetData.metadata.number_of_time_steps;
|
|
82
|
+
repeat_mode = glyphsetData.metadata.repeat_mode;
|
|
83
|
+
numberOfVertices = glyphsetData.metadata.number_of_vertices;
|
|
84
|
+
if (repeat_mode == "AXES_2D" || repeat_mode == "MIRROR")
|
|
85
|
+
numberOfVertices = numberOfVertices * 2;
|
|
86
|
+
else if (repeat_mode == "AXES_3D")
|
|
87
|
+
numberOfVertices = numberOfVertices * 3;
|
|
88
|
+
baseSize = glyphsetData.metadata.base_size;
|
|
89
|
+
offset = glyphsetData.metadata.offset;
|
|
90
|
+
scaleFactors = glyphsetData.metadata.scale_factors;
|
|
91
|
+
const loader = new JSONLoader();
|
|
92
|
+
this.geometry = new THREE.BufferGeometry();
|
|
93
|
+
this.morph = new THREE.InstancedMesh(this.geometry, undefined, numberOfVertices);
|
|
94
|
+
if (isInline) {
|
|
95
|
+
var object = loader.parse(glyphURL);
|
|
96
|
+
(meshloader(finishCallback, displayLabels))(object.geometry, object.materials);
|
|
97
|
+
object.geometry.dispose();
|
|
98
|
+
} else {
|
|
99
|
+
loader.crossOrigin = "Anonymous";
|
|
100
|
+
loader.load(glyphURL, meshloader(finishCallback, displayLabels));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Calculate the actual transformation value that can be applied
|
|
106
|
+
* to the transformation matrix.
|
|
107
|
+
* @returns {Array}
|
|
108
|
+
*/
|
|
109
|
+
const resolve_glyph_axes = (point, axis1, axis2, axis3, scale, return_arrays) => {
|
|
110
|
+
if (repeat_mode == "NONE" || repeat_mode == "MIRROR") {
|
|
111
|
+
let axis_scale = [0.0, 0.0, 0.0];
|
|
112
|
+
let final_axis1 = [0.0, 0.0, 0.0];
|
|
113
|
+
let final_axis2 = [0.0, 0.0, 0.0];
|
|
114
|
+
let final_axis3 = [0.0, 0.0, 0.0];
|
|
115
|
+
let final_point = [0.0, 0.0, 0.0];
|
|
116
|
+
const mirrored_axis1 = [0.0, 0.0, 0.0];
|
|
117
|
+
const mirrored_axis2 = [0.0, 0.0, 0.0];
|
|
118
|
+
const mirrored_axis3 = [0.0, 0.0, 0.0];
|
|
119
|
+
const mirrored_point = [0.0, 0.0, 0.0];
|
|
120
|
+
for (var j = 0; j < 3; j++) {
|
|
121
|
+
var sign = (scale[j] < 0.0) ? -1.0 : 1.0;
|
|
122
|
+
axis_scale[j] = sign * baseSize[j] + scale[j] * scaleFactors[j];
|
|
123
|
+
}
|
|
124
|
+
for (var j = 0; j < 3; j++) {
|
|
125
|
+
final_axis1[j] = axis1[j] * axis_scale[0];
|
|
126
|
+
final_axis2[j] = axis2[j] * axis_scale[1];
|
|
127
|
+
final_axis3[j] = axis3[j] * axis_scale[2];
|
|
128
|
+
final_point[j] = point[j]
|
|
129
|
+
+ offset[0] * final_axis1[j]
|
|
130
|
+
+ offset[1] * final_axis2[j]
|
|
131
|
+
+ offset[2] * final_axis3[j];
|
|
132
|
+
if (repeat_mode == "MIRROR") {
|
|
133
|
+
mirrored_axis1[j] = -final_axis1[j];
|
|
134
|
+
mirrored_axis2[j] = -final_axis2[j];
|
|
135
|
+
mirrored_axis3[j] = -final_axis3[j];
|
|
136
|
+
mirrored_point[j] = final_point[j];
|
|
137
|
+
if (scale[0] < 0.0) {
|
|
138
|
+
// shift glyph origin to end of axis1
|
|
139
|
+
final_point[j] -= final_axis1[j];
|
|
140
|
+
mirrored_point[j] -= mirrored_axis1[j];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/* if required, reverse axis3 to maintain right-handed coordinate system */
|
|
145
|
+
if (0.0 > (
|
|
146
|
+
final_axis3[0] * (final_axis1[1] * final_axis2[2] -
|
|
147
|
+
final_axis1[2] * final_axis2[1]) +
|
|
148
|
+
final_axis3[1] * (final_axis1[2] * final_axis2[0] -
|
|
149
|
+
final_axis1[0] * final_axis2[2]) +
|
|
150
|
+
final_axis3[2] * (final_axis1[0] * final_axis2[1] -
|
|
151
|
+
final_axis1[1] * final_axis2[0]))) {
|
|
152
|
+
final_axis3[0] = -final_axis3[0];
|
|
153
|
+
final_axis3[1] = -final_axis3[1];
|
|
154
|
+
final_axis3[2] = -final_axis3[2];
|
|
155
|
+
}
|
|
156
|
+
return_arrays[0] = [final_point, final_axis1, final_axis2, final_axis3];
|
|
157
|
+
if (repeat_mode == "MIRROR") {
|
|
158
|
+
if (0.0 > (
|
|
159
|
+
mirrored_axis3[0] * (mirrored_axis1[1] * mirrored_axis2[2] -
|
|
160
|
+
mirrored_axis1[2] * mirrored_axis2[1]) +
|
|
161
|
+
mirrored_axis3[1] * (mirrored_axis1[2] * mirrored_axis2[0] -
|
|
162
|
+
mirrored_axis1[0] * mirrored_axis2[2]) +
|
|
163
|
+
mirrored_axis3[2] * (mirrored_axis1[0] * mirrored_axis2[1] -
|
|
164
|
+
mirrored_axis1[1] * mirrored_axis2[0]))) {
|
|
165
|
+
mirrored_axis3[0] = -mirrored_axis3[0];
|
|
166
|
+
mirrored_axis3[1] = -mirrored_axis3[1];
|
|
167
|
+
mirrored_axis3[2] = -mirrored_axis3[2];
|
|
168
|
+
}
|
|
169
|
+
return_arrays[1] =[mirrored_point, mirrored_axis1, mirrored_axis2, mirrored_axis3];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (repeat_mode == "AXES_2D" || repeat_mode == "AXES_3D") {
|
|
173
|
+
let axis_scale = [0.0, 0.0, 0.0];
|
|
174
|
+
let final_point = [0.0, 0.0, 0.0];
|
|
175
|
+
for (var j = 0; j < 3; j++) {
|
|
176
|
+
var sign = (scale[j] < 0.0) ? -1.0 : 1.0;
|
|
177
|
+
axis_scale[j] = sign * baseSize[0] + scale[j] * scaleFactors[0];
|
|
178
|
+
}
|
|
179
|
+
for (var j = 0; j < 3; j++) {
|
|
180
|
+
final_point[j] = point[j]
|
|
181
|
+
+ offset[0] * axis_scale[0] * axis1[j]
|
|
182
|
+
+ offset[1] * axis_scale[1] * axis2[j]
|
|
183
|
+
+ offset[2] * axis_scale[2] * axis3[j];
|
|
184
|
+
}
|
|
185
|
+
const number_of_glyphs = (glyph_repeat_mode == "AXES_2D") ? 2 : 3;
|
|
186
|
+
for (let k = 0; k < number_of_glyphs; k++) {
|
|
187
|
+
let use_axis1, use_axis2;
|
|
188
|
+
const use_scale = scale[k];
|
|
189
|
+
let final_axis1 = [0.0, 0.0, 0.0];
|
|
190
|
+
let final_axis2 = [0.0, 0.0, 0.0];
|
|
191
|
+
let final_axis3 = [0.0, 0.0, 0.0];
|
|
192
|
+
if (k == 0) {
|
|
193
|
+
use_axis1 = axis1;
|
|
194
|
+
use_axis2 = axis2;
|
|
195
|
+
}
|
|
196
|
+
else if (k == 1) {
|
|
197
|
+
use_axis1 = axis2;
|
|
198
|
+
use_axis2 = (glyph_repeat_mode == "AXES_2D") ? axis1 : axis3;
|
|
199
|
+
}
|
|
200
|
+
else // if (k == 2)
|
|
201
|
+
{
|
|
202
|
+
use_axis1 = axis3;
|
|
203
|
+
use_axis2 = axis1;
|
|
204
|
+
}
|
|
205
|
+
const final_scale1 = baseSize[0] + use_scale * scaleFactors[0];
|
|
206
|
+
final_axis1[0] = use_axis1[0] * final_scale1;
|
|
207
|
+
final_axis1[1] = use_axis1[1] * final_scale1;
|
|
208
|
+
final_axis1[2] = use_axis1[2] * final_scale1;
|
|
209
|
+
final_axis3[0] = final_axis1[1] * use_axis2[2] - use_axis2[1] * final_axis1[2];
|
|
210
|
+
final_axis3[1] = final_axis1[2] * use_axis2[0] - use_axis2[2] * final_axis1[0];
|
|
211
|
+
final_axis3[2] = final_axis1[0] * use_axis2[1] - final_axis1[1] * use_axis2[0];
|
|
212
|
+
let magnitude = Math.sqrt(final_axis3[0] * final_axis3[0] + final_axis3[1] * final_axis3[1] + final_axis3[2] * final_axis3[2]);
|
|
213
|
+
if (0.0 < magnitude) {
|
|
214
|
+
let scaling = (baseSize[2] + use_scale * scaleFactors[2]) / magnitude;
|
|
215
|
+
if ((repeat_mode == "AXES_2D") && (k > 0)) {
|
|
216
|
+
scaling *= -1.0;
|
|
217
|
+
}
|
|
218
|
+
final_axis3[0] *= scaling;
|
|
219
|
+
final_axis3[1] *= scaling;
|
|
220
|
+
final_axis3[2] *= scaling;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
final_axis2[0] = final_axis3[1] * final_axis1[2] - final_axis1[1] * final_axis3[2];
|
|
224
|
+
final_axis2[1] = final_axis3[2] * final_axis1[0] - final_axis1[2] * final_axis3[0];
|
|
225
|
+
final_axis2[2] = final_axis3[0] * final_axis1[1] - final_axis3[1] * final_axis1[0];
|
|
226
|
+
magnitude = Math.sqrt(final_axis2[0] * final_axis2[0] + final_axis2[1] * final_axis2[1] + final_axis2[2] * final_axis2[2]);
|
|
227
|
+
if (0.0 < magnitude) {
|
|
228
|
+
var scaling = (baseSize[1] + use_scale * scaleFactors[1]) / magnitude;
|
|
229
|
+
final_axis2[0] *= scaling;
|
|
230
|
+
final_axis2[1] *= scaling;
|
|
231
|
+
final_axis2[2] *= scaling;
|
|
232
|
+
}
|
|
233
|
+
return_arrays[k] = [final_point, final_axis1, final_axis2, final_axis3];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return return_arrays;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Update transformation for each of the glyph in this glyphset.
|
|
241
|
+
*/
|
|
242
|
+
const updateGlyphsetTransformation = (
|
|
243
|
+
current_positions,
|
|
244
|
+
current_axis1s,
|
|
245
|
+
current_axis2s,
|
|
246
|
+
current_axis3s,
|
|
247
|
+
current_scales
|
|
248
|
+
) => {
|
|
249
|
+
let numberOfGlyphs = 1;
|
|
250
|
+
if (repeat_mode == "AXES_2D" || repeat_mode == "MIRROR")
|
|
251
|
+
numberOfGlyphs = 2;
|
|
252
|
+
else if (repeat_mode == "AXES_3D")
|
|
253
|
+
numberOfGlyphs = 3;
|
|
254
|
+
const numberOfPositions = current_positions.length / 3;
|
|
255
|
+
let current_glyph_index = 0;
|
|
256
|
+
_glyph_axis_array.length = numberOfGlyphs;
|
|
257
|
+
for (let i = 0; i < numberOfPositions; i++) {
|
|
258
|
+
const current_index = i * 3;
|
|
259
|
+
const current_position = [current_positions[current_index], current_positions[current_index + 1],
|
|
260
|
+
current_positions[current_index + 2]];
|
|
261
|
+
const current_axis1 = [current_axis1s[current_index], current_axis1s[current_index + 1],
|
|
262
|
+
current_axis1s[current_index + 2]];
|
|
263
|
+
const current_axis2 = [current_axis2s[current_index], current_axis2s[current_index + 1],
|
|
264
|
+
current_axis2s[current_index + 2]];
|
|
265
|
+
const current_axis3 = [current_axis3s[current_index], current_axis3s[current_index + 1],
|
|
266
|
+
current_axis3s[current_index + 2]];
|
|
267
|
+
const current_scale = [current_scales[current_index], current_scales[current_index + 1],
|
|
268
|
+
current_scales[current_index + 2]];
|
|
269
|
+
const arrays = resolve_glyph_axes(current_position, current_axis1, current_axis2,
|
|
270
|
+
current_axis3, current_scale, _glyph_axis_array);
|
|
271
|
+
if (arrays.length == numberOfGlyphs) {
|
|
272
|
+
for (let j = 0; j < numberOfGlyphs; j++) {
|
|
273
|
+
_transformMatrix.elements[0] = arrays[j][1][0];
|
|
274
|
+
_transformMatrix.elements[1] = arrays[j][1][1];
|
|
275
|
+
_transformMatrix.elements[2] = arrays[j][1][2];
|
|
276
|
+
_transformMatrix.elements[3] = 0.0;
|
|
277
|
+
_transformMatrix.elements[4] = arrays[j][2][0];
|
|
278
|
+
_transformMatrix.elements[5] = arrays[j][2][1];
|
|
279
|
+
_transformMatrix.elements[6] = arrays[j][2][2];
|
|
280
|
+
_transformMatrix.elements[7] = 0.0;
|
|
281
|
+
_transformMatrix.elements[8] = arrays[j][3][0];
|
|
282
|
+
_transformMatrix.elements[9] = arrays[j][3][1];
|
|
283
|
+
_transformMatrix.elements[10] = arrays[j][3][2];
|
|
284
|
+
_transformMatrix.elements[11] = 0.0;
|
|
285
|
+
_transformMatrix.elements[12] = arrays[j][0][0];
|
|
286
|
+
_transformMatrix.elements[13] = arrays[j][0][1];
|
|
287
|
+
_transformMatrix.elements[14] = arrays[j][0][2];
|
|
288
|
+
_transformMatrix.elements[15] = 1.0;
|
|
289
|
+
this.morph.setMatrixAt(current_glyph_index, _transformMatrix);
|
|
290
|
+
const glyph = glyphList[current_glyph_index];
|
|
291
|
+
if (glyph)
|
|
292
|
+
glyph.setTransformation(arrays[j][0], arrays[j][1],
|
|
293
|
+
arrays[j][2], arrays[j][3]);
|
|
294
|
+
current_glyph_index++;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
this.morph.instanceMatrix.needsUpdate = true;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Update colour for each of the glyph in this glyphset.
|
|
303
|
+
*/
|
|
304
|
+
const updateGlyphsetHexColors = current_colors => {
|
|
305
|
+
let numberOfGlyphs = 1;
|
|
306
|
+
if (repeat_mode == "AXES_2D" || repeat_mode == "MIRROR")
|
|
307
|
+
numberOfGlyphs = 2;
|
|
308
|
+
else if (repeat_mode == "AXES_3D")
|
|
309
|
+
numberOfGlyphs = 3;
|
|
310
|
+
const numberOfColours = current_colors.length;
|
|
311
|
+
let current_glyph_index = 0;
|
|
312
|
+
for (let i = 0; i < numberOfColours; i++) {
|
|
313
|
+
const hex_values = current_colors[i];
|
|
314
|
+
for (let j = 0; j < numberOfGlyphs; j++) {
|
|
315
|
+
_bot_colour.setHex(hex_values)
|
|
316
|
+
this.morph.setColorAt(current_glyph_index, _bot_colour);
|
|
317
|
+
const glyph = glyphList[current_glyph_index];
|
|
318
|
+
if (glyph)
|
|
319
|
+
glyph.setColour(_bot_colour);
|
|
320
|
+
current_glyph_index++;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
this.morph.instanceColor.needsUpdate = true;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Update the current states of the glyphs in this glyphset, this includes transformation and
|
|
328
|
+
* colour for each of them. This is called when glyphset and glyphs are initialised and whenever
|
|
329
|
+
* the internal time has been updated.
|
|
330
|
+
*/
|
|
331
|
+
const updateMorphGlyphsets = () => {
|
|
332
|
+
const current_positions = _current_positions;
|
|
333
|
+
const current_axis1s = _current_axis1s;
|
|
334
|
+
const current_axis2s = _current_axis2s;
|
|
335
|
+
const current_axis3s = _current_axis3s;
|
|
336
|
+
const current_scales = _current_scales;
|
|
337
|
+
const current_colors = _current_colors;
|
|
338
|
+
|
|
339
|
+
const current_time = this.inbuildTime / this.duration * (numberOfTimeSteps - 1);
|
|
340
|
+
const bottom_frame = Math.floor(current_time);
|
|
341
|
+
const proportion = 1 - (current_time - bottom_frame);
|
|
342
|
+
const top_frame = Math.ceil(current_time);
|
|
343
|
+
if (morphVertices) {
|
|
344
|
+
const bottom_positions = positions[bottom_frame.toString()];
|
|
345
|
+
const top_positions = positions[top_frame.toString()];
|
|
346
|
+
const bottom_axis1 = axis1s[bottom_frame.toString()];
|
|
347
|
+
const top_axis1 = axis1s[top_frame.toString()];
|
|
348
|
+
const bottom_axis2 = axis2s[bottom_frame.toString()];
|
|
349
|
+
const top_axis2 = axis2s[top_frame.toString()];
|
|
350
|
+
const bottom_axis3 = axis3s[bottom_frame.toString()];
|
|
351
|
+
const top_axis3 = axis3s[top_frame.toString()];
|
|
352
|
+
const bottom_scale = scales[bottom_frame.toString()];
|
|
353
|
+
const top_scale = scales[top_frame.toString()];
|
|
354
|
+
_current_positions.length = bottom_positions.length;
|
|
355
|
+
_current_axis1s.length = bottom_positions.length;
|
|
356
|
+
_current_axis2s.length = bottom_positions.length;
|
|
357
|
+
_current_axis3s.length = bottom_positions.length;
|
|
358
|
+
_current_scales.length = bottom_positions.length;
|
|
359
|
+
|
|
360
|
+
for (let i = 0; i < bottom_positions.length; i++) {
|
|
361
|
+
current_positions[i] = proportion * bottom_positions[i] + (1.0 - proportion) * top_positions[i];
|
|
362
|
+
current_axis1s[i] = proportion * bottom_axis1[i] + (1.0 - proportion) * top_axis1[i];
|
|
363
|
+
current_axis2s[i] = proportion * bottom_axis2[i] + (1.0 - proportion) * top_axis2[i];
|
|
364
|
+
current_axis3s[i] = proportion * bottom_axis3[i] + (1.0 - proportion) * top_axis3[i];
|
|
365
|
+
current_scales[i] = proportion * bottom_scale[i] + (1.0 - proportion) * top_scale[i];
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
current_positions = positions["0"];
|
|
369
|
+
current_axis1s = axis1s["0"];
|
|
370
|
+
current_axis2s = axis2s["0"];
|
|
371
|
+
current_axis3s = axis3s["0"];
|
|
372
|
+
current_scales = scales["0"];
|
|
373
|
+
}
|
|
374
|
+
updateGlyphsetTransformation(current_positions, current_axis1s, current_axis2s, current_axis3s,
|
|
375
|
+
current_scales);
|
|
376
|
+
this.boundingBoxUpdateRequired = true;
|
|
377
|
+
if (colors != undefined) {
|
|
378
|
+
if (morphColours) {
|
|
379
|
+
const bottom_colors = colors[bottom_frame.toString()];
|
|
380
|
+
const top_colors = colors[top_frame.toString()];
|
|
381
|
+
current_colors.length = bottom_colors.length;
|
|
382
|
+
for (let i = 0; i < bottom_colors.length; i++) {
|
|
383
|
+
_bot_colour.setHex(bottom_colors[i]);
|
|
384
|
+
_top_colour.setHex(top_colors[i]);
|
|
385
|
+
_bot_colour.setRGB(_bot_colour.r * proportion + _top_colour.r * (1 - proportion),
|
|
386
|
+
_bot_colour.g * proportion + _top_colour.g * (1 - proportion),
|
|
387
|
+
_bot_colour.b * proportion + _top_colour.b * (1 - proportion));
|
|
388
|
+
current_colors[i] = _bot_colour.getHex();
|
|
389
|
+
}
|
|
390
|
+
/*
|
|
391
|
+
for (var i = 0; i < bottom_colors.length; i++) {
|
|
392
|
+
current_colors.push(proportion * bottom_colors[i] + (1.0 - proportion) * top_colors[i]);
|
|
393
|
+
}
|
|
394
|
+
*/
|
|
395
|
+
} else {
|
|
396
|
+
current_colors = colors["0"];
|
|
397
|
+
}
|
|
398
|
+
updateGlyphsetHexColors(current_colors);
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
this.showLabel = () => {
|
|
403
|
+
for (let i = 0; i < glyphList.length; i++) {
|
|
404
|
+
glyphList[i].showLabel(this.morph.material ? this.morph.material.color : undefined);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const createGlyphs = (displayLabels) => {
|
|
409
|
+
if ((labels != undefined) && displayLabels) {
|
|
410
|
+
for (let i = 0; i < numberOfVertices; i++) {
|
|
411
|
+
const glyph = new (require('./glyph').Glyph)(undefined, undefined, i, this);
|
|
412
|
+
if (labels != undefined && labels[i] != undefined) {
|
|
413
|
+
glyph.setLabel(labels[i]);
|
|
414
|
+
}
|
|
415
|
+
if (numberOfTimeSteps > 0) {
|
|
416
|
+
glyph.setFrustumCulled(false);
|
|
417
|
+
}
|
|
418
|
+
glyphList[i] = glyph;
|
|
419
|
+
this.morph.add(glyph.getGroup());
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if ((labels != undefined) && displayLabels) {
|
|
423
|
+
this.showLabel(this.morph.material ? this.morph.material.color : undefined);
|
|
424
|
+
}
|
|
425
|
+
//Update the transformation of the glyphs.
|
|
426
|
+
updateGlyphsetTransformation(positions["0"], axis1s["0"],
|
|
427
|
+
axis2s["0"], axis3s["0"], scales["0"]);
|
|
428
|
+
//Update the color of the glyphs.
|
|
429
|
+
if (colors != undefined) {
|
|
430
|
+
updateGlyphsetHexColors(colors["0"]);
|
|
431
|
+
}
|
|
432
|
+
this.ready = true;
|
|
433
|
+
this.boundingBoxUpdateRequired = true;
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
this.addCustomGlyph = glyph => {
|
|
437
|
+
if (glyph.isGlyph)
|
|
438
|
+
glyphList.push(glyph);
|
|
439
|
+
this.ready = true;
|
|
440
|
+
this.boundingBoxUpdateRequired = true;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
this.addMeshAsGlyph = (mesh, id) => {
|
|
444
|
+
if (mesh.isMesh) {
|
|
445
|
+
const glyph = new (require('./glyph').Glyph)(undefined, undefined, id, this);
|
|
446
|
+
glyph.fromMesh(mesh);
|
|
447
|
+
glyphList.push(glyph);
|
|
448
|
+
this.morph.add(glyph.getGroup())
|
|
449
|
+
this.ready = true;
|
|
450
|
+
this.boundingBoxUpdateRequired = true;
|
|
451
|
+
return glyph;
|
|
452
|
+
}
|
|
453
|
+
return undefined;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* A function which iterates through the list of glyphs and call the callback
|
|
458
|
+
* function with the glyph as the argument.
|
|
459
|
+
* @param {Function} callbackFunction - Callback function with the glyph
|
|
460
|
+
* as an argument.
|
|
461
|
+
*/
|
|
462
|
+
this.forEachGlyph = callbackFunction => {
|
|
463
|
+
for (let i = 0; i < glyphList.length; i++) {
|
|
464
|
+
callbackFunction(glyphList[i]);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
var meshloader = (finishCallback, displayLabels) => {
|
|
469
|
+
return (geometry, materials) => {
|
|
470
|
+
const tempGeometry = geometry.toBufferGeometry();
|
|
471
|
+
this.geometry.copy(tempGeometry);
|
|
472
|
+
this.geometry.computeBoundingSphere();
|
|
473
|
+
this.geometry.computeBoundingBox();
|
|
474
|
+
tempGeometry.dispose();
|
|
475
|
+
if (materials && materials[0])
|
|
476
|
+
this.morph.material = materials[0];
|
|
477
|
+
createGlyphs(displayLabels);
|
|
478
|
+
this.morph.name = this.groupName;
|
|
479
|
+
this.morph.userData = this;
|
|
480
|
+
geometry.dispose();
|
|
481
|
+
if (finishCallback != undefined && (typeof finishCallback == 'function'))
|
|
482
|
+
finishCallback(this);
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Get the index of the closest vertex to centroid.
|
|
488
|
+
*/
|
|
489
|
+
this.getClosestVertexIndex = function () {
|
|
490
|
+
let closestIndex = -1;
|
|
491
|
+
if (this.morph && this.ready) {
|
|
492
|
+
let center = new THREE.Vector3();
|
|
493
|
+
this.getBoundingBox().getCenter(center);
|
|
494
|
+
let current_positions = positions["0"];
|
|
495
|
+
const numberOfPositions = current_positions.length / 3;
|
|
496
|
+
let position = new THREE.Vector3();
|
|
497
|
+
let distance = -1;
|
|
498
|
+
let currentDistance = 0;
|
|
499
|
+
for (let i = 0; i < numberOfPositions; i++) {
|
|
500
|
+
const current_index = i * 3;
|
|
501
|
+
position.set(current_positions[current_index],
|
|
502
|
+
current_positions[current_index + 1],
|
|
503
|
+
current_positions[current_index + 2]);
|
|
504
|
+
currentDistance = center.distanceTo(position);
|
|
505
|
+
if (distance == -1) {
|
|
506
|
+
distance = currentDistance;
|
|
507
|
+
closestIndex = i;
|
|
508
|
+
} else if (distance > currentDistance) {
|
|
509
|
+
distance = currentDistance;
|
|
510
|
+
closestIndex = i;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return closestIndex;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Get the closest vertex to centroid.
|
|
519
|
+
*/
|
|
520
|
+
this.getClosestVertex = function () {
|
|
521
|
+
|
|
522
|
+
if (this.closestVertexIndex == -1) {
|
|
523
|
+
this.closestVertexIndex = this.getClosestVertexIndex();
|
|
524
|
+
}
|
|
525
|
+
if (this.closestVertexIndex >= 0) {
|
|
526
|
+
/*
|
|
527
|
+
if (glyphList && glyphList[this.closestVertexIndex]) {
|
|
528
|
+
glyphList[this.closestVertexIndex].getBoundingBox().getCenter(position);
|
|
529
|
+
}
|
|
530
|
+
*/
|
|
531
|
+
if (this.morph) {
|
|
532
|
+
let position = new THREE.Vector3();
|
|
533
|
+
this.morph.getMatrixAt(this.closestVertexIndex, _transformMatrix);
|
|
534
|
+
position.setFromMatrixPosition(_transformMatrix);
|
|
535
|
+
return position;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
this.applyMatrix4ToBox = (box1, box2, matrix) => {
|
|
543
|
+
_points[0].set(box1.min.x, box1.min.y, box1.min.z).applyMatrix4(matrix); // 000
|
|
544
|
+
_points[1].set(box1.min.x, box1.min.y, box1.max.z).applyMatrix4(matrix); // 001
|
|
545
|
+
_points[2].set(box1.min.x, box1.max.y, box1.min.z).applyMatrix4(matrix); // 010
|
|
546
|
+
_points[3].set(box1.min.x, box1.max.y, box1.max.z).applyMatrix4(matrix); // 011
|
|
547
|
+
_points[4].set(box1.max.x, box1.min.y, box1.min.z).applyMatrix4(matrix); // 100
|
|
548
|
+
_points[5].set(box1.max.x, box1.min.y, box1.max.z).applyMatrix4(matrix); // 101
|
|
549
|
+
_points[6].set(box1.max.x, box1.max.y, box1.min.z).applyMatrix4(matrix); // 110
|
|
550
|
+
_points[7].set(box1.max.x, box1.max.y, box1.max.z).applyMatrix4(matrix); // 111
|
|
551
|
+
box2.setFromPoints(_points);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Get the bounding box for the whole set of glyphs.
|
|
557
|
+
*
|
|
558
|
+
* @return {Three.Box3};
|
|
559
|
+
*/
|
|
560
|
+
this.getBoundingBox = () => {
|
|
561
|
+
if (this.morph && this.ready && this.morph.visible) {
|
|
562
|
+
if (this.boundingBoxUpdateRequired) {
|
|
563
|
+
_boundingBox1.setFromBufferAttribute(
|
|
564
|
+
this.morph.geometry.attributes.position);
|
|
565
|
+
for (let i = 0; i < numberOfVertices; i++) {
|
|
566
|
+
this.morph.getMatrixAt(i, _transformMatrix);
|
|
567
|
+
this.applyMatrix4ToBox(_boundingBox1, _boundingBox2, _transformMatrix);
|
|
568
|
+
if (i == 0) {
|
|
569
|
+
_boundingBox3.copy(_boundingBox2);
|
|
570
|
+
} else {
|
|
571
|
+
_boundingBox3.union(_boundingBox2);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
if (_boundingBox3) {
|
|
575
|
+
this.cachedBoundingBox.copy(_boundingBox3);
|
|
576
|
+
this.boundingBoxUpdateRequired = false;
|
|
577
|
+
} else
|
|
578
|
+
return undefined;
|
|
579
|
+
}
|
|
580
|
+
return this.cachedBoundingBox;
|
|
581
|
+
}
|
|
582
|
+
return undefined;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Set the local time of this glyphset.
|
|
587
|
+
*
|
|
588
|
+
* @param {Number} time - Can be any value between 0 to duration.
|
|
589
|
+
*/
|
|
590
|
+
this.setMorphTime = time => {
|
|
591
|
+
if (time > this.duration)
|
|
592
|
+
this.inbuildTime = this.duration;
|
|
593
|
+
else if (0 > time)
|
|
594
|
+
this.inbuildTime = 0;
|
|
595
|
+
else
|
|
596
|
+
this.inbuildTime = time;
|
|
597
|
+
if (morphColours || morphVertices) {
|
|
598
|
+
updateMorphGlyphsets();
|
|
599
|
+
if (morphVertices)
|
|
600
|
+
this.markerUpdateRequired = true;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Check if the glyphset is time varying.
|
|
606
|
+
*
|
|
607
|
+
* @return {Boolean}
|
|
608
|
+
*/
|
|
609
|
+
this.isTimeVarying = () => {
|
|
610
|
+
if ((numberOfTimeSteps > 0) && (morphColours || morphVertices))
|
|
611
|
+
return true;
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
this.getCurrentTime = () => {
|
|
616
|
+
return this.inbuildTime;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Clear this glyphset and its list of glyphs which will release them from the memory.
|
|
622
|
+
*/
|
|
623
|
+
this.dispose = () => {
|
|
624
|
+
for (let i = glyphList.length - 1; i >= 0; i--) {
|
|
625
|
+
glyphList[i].dispose();
|
|
626
|
+
}
|
|
627
|
+
if (this.geometry)
|
|
628
|
+
this.geometry.dispose();
|
|
629
|
+
if (this.morph)
|
|
630
|
+
this.morph.material.dispose();
|
|
631
|
+
axis1s = undefined;
|
|
632
|
+
axis2s = undefined;
|
|
633
|
+
axis3s = undefined;
|
|
634
|
+
positions = undefined;
|
|
635
|
+
scales = undefined;
|
|
636
|
+
colors = undefined;
|
|
637
|
+
this.ready = false;
|
|
638
|
+
this.groupName = undefined;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
//Update the geometry and colours depending on the morph.
|
|
642
|
+
this.render = (delta, playAnimation, options) => {
|
|
643
|
+
if (playAnimation == true) {
|
|
644
|
+
let targetTime = this.inbuildTime + delta;
|
|
645
|
+
if (targetTime > this.duration)
|
|
646
|
+
targetTime = targetTime - this.duration
|
|
647
|
+
this.inbuildTime = targetTime;
|
|
648
|
+
if (morphColours || morphVertices) {
|
|
649
|
+
updateMorphGlyphsets();
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
this.updateMarker(playAnimation, options);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
Glyphset.prototype = Object.create((require('./zincObject').ZincObject).prototype);
|
|
657
|
+
exports.Glyphset = Glyphset;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const SpriteText = require('three-spritetext').default;
|
|
2
|
+
|
|
3
|
+
exports.Label = function ( textIn, colour ) {
|
|
4
|
+
let text = textIn;
|
|
5
|
+
let sprite = undefined;
|
|
6
|
+
if (colour)
|
|
7
|
+
sprite = new SpriteText(text, 0.015, colour.getStyle());
|
|
8
|
+
else
|
|
9
|
+
sprite = new SpriteText(text, 0.015);
|
|
10
|
+
sprite.material.sizeAttenuation = false;
|
|
11
|
+
sprite.center.x = -0.05;
|
|
12
|
+
sprite.center.y = 0;
|
|
13
|
+
|
|
14
|
+
this.getPosition = () => {
|
|
15
|
+
if (sprite)
|
|
16
|
+
return [sprite.position.x, sprite.position.y, sprite.position.z];
|
|
17
|
+
return [0, 0, 0];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//now set the position at the correct 3D space
|
|
21
|
+
this.setPosition = (x, y, z) => {
|
|
22
|
+
if (sprite)
|
|
23
|
+
sprite.position.set(x, y, z);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.setColour = colour => {
|
|
27
|
+
sprite.color = colour.getStyle();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//scale up the texture
|
|
31
|
+
this.setScale = scaling => {
|
|
32
|
+
if (sprite && scaling > 0.0)
|
|
33
|
+
sprite.scale.set( scaling, scaling, 1.0 );
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.dispose = () => {
|
|
37
|
+
sprite.dispose();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.getSprite = () => {
|
|
41
|
+
return sprite;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.getString = () => {
|
|
45
|
+
return text;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|