zincjs 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +27 -22
  2. package/build/zinc.js +2 -2
  3. package/build/zinc.js.map +1 -1
  4. package/package.json +4 -1
  5. package/src/controls.js +1332 -1241
  6. package/src/geometryCSG.js +111 -115
  7. package/src/glyphsetCSG.js +51 -55
  8. package/src/loaders/GLTFToZincJSLoader.js +31 -33
  9. package/src/loaders/JSONLoader.js +339 -449
  10. package/src/loaders/OBJLoader.js +654 -851
  11. package/src/loaders/STLLoader.js +271 -329
  12. package/src/loaders/niftiReader.js +90 -59
  13. package/src/loaders/primitivesLoader.js +55 -52
  14. package/src/minimap.js +63 -43
  15. package/src/primitives/geometry.js +40 -44
  16. package/src/primitives/glyph.js +16 -19
  17. package/src/primitives/glyphset.js +229 -185
  18. package/src/primitives/label.js +29 -31
  19. package/src/primitives/lines.js +20 -20
  20. package/src/primitives/lines2.js +33 -39
  21. package/src/primitives/lod.js +43 -43
  22. package/src/primitives/marker.js +31 -32
  23. package/src/primitives/markerCluster.js +32 -35
  24. package/src/primitives/pointset.js +86 -83
  25. package/src/primitives/texturePrimitive.js +9 -10
  26. package/src/primitives/textureSlides.js +84 -97
  27. package/src/primitives/textureVolume.js +46 -49
  28. package/src/primitives/tubeLines.js +108 -108
  29. package/src/primitives/zincObject.js +176 -184
  30. package/src/region.js +145 -155
  31. package/src/renderRequests.js +3 -3
  32. package/src/renderer.js +635 -620
  33. package/src/scene.js +479 -419
  34. package/src/sceneExporter.js +22 -17
  35. package/src/sceneLoader.js +542 -296
  36. package/src/shaders/rgbVolumeRender.js +11 -18
  37. package/src/shaders/textureArray.js +5 -12
  38. package/src/shaders/textureSlide.js +10 -17
  39. package/src/shaders/volumeRender.js +11 -18
  40. package/src/shaders/volumeRender_old.js +11 -18
  41. package/src/shaders/volumeTexture.js +7 -14
  42. package/src/textSprite.js +23 -19
  43. package/src/texture/texture.js +14 -15
  44. package/src/texture/textureArray.js +14 -16
  45. package/src/three/InstancedPoints.js +2 -9
  46. package/src/three/Loader.js +334 -315
  47. package/src/three/line/Line.js +165 -215
  48. package/src/three/line/LineSegments.js +40 -55
  49. package/src/three/line/LineSegments2.js +322 -366
  50. package/src/three/line/LineSegmentsGeometry.js +239 -280
  51. package/src/three-js-csg.js +260 -252
  52. package/src/tsl/glyphRenderMaterial.js +12 -3
  53. package/src/tsl/glyphTransform.js +51 -29
  54. package/src/tsl/textureSlides.js +23 -24
  55. package/src/utilities.js +309 -371
  56. package/src/videoHandler.js +76 -83
  57. package/src/workers/geometryCSG.worker.js +33 -36
  58. package/src/workers/geometryCSGInternal.js +39 -44
  59. package/src/zinc.js +4 -7
  60. package/vite.config.js +7 -7
@@ -3,8 +3,12 @@ import { Glyph } from './glyph';
3
3
  import { ZincObject } from './zincObject';
4
4
  import { updateWorldMatrixFromAncestors } from '../utilities';
5
5
  import { JSONLoader } from '../loaders/JSONLoader';
6
- import { createGlyphTransformCompute, dispatchAndReadbackGlyphTransform, isGlyphComputeSupported,
7
- readbackGlyphTransform } from '../tsl/glyphTransform';
6
+ import {
7
+ createGlyphTransformCompute,
8
+ dispatchAndReadbackGlyphTransform,
9
+ isGlyphComputeSupported,
10
+ readbackGlyphTransform,
11
+ } from '../tsl/glyphTransform';
8
12
  import { createGlyphInstancedMaterial } from '../tsl/glyphRenderMaterial';
9
13
 
10
14
  /**
@@ -35,7 +39,7 @@ const Glyphset = function () {
35
39
  let offset = [0, 0, 0];
36
40
  let labelsOn = false;
37
41
  let scaleFactors = [0, 0, 0];
38
- let repeat_mode = "NONE";
42
+ let repeat_mode = 'NONE';
39
43
  this.ready = false;
40
44
  let morphColours = false;
41
45
  let morphVertices = false;
@@ -102,7 +106,7 @@ const Glyphset = function () {
102
106
  matrix.elements[13] = arrayTuple[0][1];
103
107
  matrix.elements[14] = arrayTuple[0][2];
104
108
  matrix.elements[15] = 1.0;
105
- }
109
+ };
106
110
 
107
111
  /**
108
112
  * Flattens a { "0": [x,y,z,...], "1": [...], ... } per-keyframe object
@@ -118,7 +122,7 @@ const Glyphset = function () {
118
122
  }
119
123
  }
120
124
  return out;
121
- }
125
+ };
122
126
 
123
127
  /**
124
128
  * Same as flattenVec3Frames but for the colours object, whose per-frame
@@ -142,7 +146,7 @@ const Glyphset = function () {
142
146
  }
143
147
  }
144
148
  return out;
145
- }
149
+ };
146
150
 
147
151
  /**
148
152
  * Copy glyphset data into this glyphset then load the glyph's geoemtry
@@ -169,18 +173,22 @@ const Glyphset = function () {
169
173
  numberOfTimeSteps = glyphsetData.metadata.number_of_time_steps;
170
174
  repeat_mode = glyphsetData.metadata.repeat_mode;
171
175
  numberOfVertices = glyphsetData.metadata.number_of_vertices;
172
- if (repeat_mode == "AXES_2D" || repeat_mode == "MIRROR")
176
+ if (repeat_mode == 'AXES_2D' || repeat_mode == 'MIRROR')
173
177
  numberOfVertices = numberOfVertices * 2;
174
- else if (repeat_mode == "AXES_3D")
175
- numberOfVertices = numberOfVertices * 3;
178
+ else if (repeat_mode == 'AXES_3D') numberOfVertices = numberOfVertices * 3;
176
179
  baseSize = glyphsetData.metadata.base_size;
177
180
  offset = glyphsetData.metadata.offset;
178
181
  scaleFactors = glyphsetData.metadata.scale_factors;
179
182
  glyphCompute = undefined;
180
183
  //The CPU path is used when the backend does not support GPU compute
181
- if (morphVertices && numberOfTimeSteps > 1 && positions && positions["0"] &&
182
- isGlyphComputeSupported()) {
183
- const baseCount = positions["0"].length / 3;
184
+ if (
185
+ morphVertices &&
186
+ numberOfTimeSteps > 1 &&
187
+ positions &&
188
+ positions['0'] &&
189
+ isGlyphComputeSupported()
190
+ ) {
191
+ const baseCount = positions['0'].length / 3;
184
192
  try {
185
193
  glyphCompute = createGlyphTransformCompute({
186
194
  baseCount,
@@ -191,14 +199,20 @@ const Glyphset = function () {
191
199
  axis2Data: flattenVec3Frames(axis2s, numberOfTimeSteps, baseCount),
192
200
  axis3Data: flattenVec3Frames(axis3s, numberOfTimeSteps, baseCount),
193
201
  scaleData: flattenVec3Frames(scales, numberOfTimeSteps, baseCount),
194
- colorData: (morphColours && colors) ? flattenColorFrames(colors, numberOfTimeSteps, baseCount) : undefined,
202
+ colorData:
203
+ morphColours && colors
204
+ ? flattenColorFrames(colors, numberOfTimeSteps, baseCount)
205
+ : undefined,
195
206
  baseSize,
196
207
  offset,
197
208
  scaleFactors,
198
209
  globalScale: this.globalScale,
199
210
  });
200
211
  } catch (err) {
201
- console.error("Failed to set up GPU glyph transform compute, falling back to CPU animation.", err);
212
+ console.error(
213
+ 'Failed to set up GPU glyph transform compute, falling back to CPU animation.',
214
+ err,
215
+ );
202
216
  glyphCompute = undefined;
203
217
  }
204
218
  }
@@ -208,13 +222,13 @@ const Glyphset = function () {
208
222
  this.setMorph(instancedMesh);
209
223
  if (isInline) {
210
224
  var object = loader.parse(glyphURL);
211
- (meshloader(finishCallback, displayLabels))(object.geometry, object.materials);
225
+ meshloader(finishCallback, displayLabels)(object.geometry, object.materials);
212
226
  object.geometry.dispose();
213
227
  } else {
214
- loader.crossOrigin = "Anonymous";
228
+ loader.crossOrigin = 'Anonymous';
215
229
  loader.load(glyphURL, meshloader(finishCallback, displayLabels));
216
230
  }
217
- }
231
+ };
218
232
 
219
233
  /**
220
234
  * Calculate the actual transformation value that can be applied
@@ -223,7 +237,7 @@ const Glyphset = function () {
223
237
  * @returns {Array}
224
238
  */
225
239
  const resolve_glyph_axes = (point, axis1, axis2, axis3, scale, return_arrays) => {
226
- if (repeat_mode == "NONE" || repeat_mode == "MIRROR") {
240
+ if (repeat_mode == 'NONE' || repeat_mode == 'MIRROR') {
227
241
  let axis_scale = [0.0, 0.0, 0.0];
228
242
  let final_axis1 = [0.0, 0.0, 0.0];
229
243
  let final_axis2 = [0.0, 0.0, 0.0];
@@ -234,18 +248,19 @@ const Glyphset = function () {
234
248
  const mirrored_axis3 = [0.0, 0.0, 0.0];
235
249
  const mirrored_point = [0.0, 0.0, 0.0];
236
250
  for (var j = 0; j < 3; j++) {
237
- var sign = (scale[j] < 0.0) ? -1.0 : 1.0;
251
+ var sign = scale[j] < 0.0 ? -1.0 : 1.0;
238
252
  axis_scale[j] = (sign * baseSize[j] + scale[j] * scaleFactors[j]) * this.globalScale;
239
253
  }
240
254
  for (var j = 0; j < 3; j++) {
241
255
  final_axis1[j] = axis1[j] * axis_scale[0];
242
256
  final_axis2[j] = axis2[j] * axis_scale[1];
243
257
  final_axis3[j] = axis3[j] * axis_scale[2];
244
- final_point[j] = point[j]
245
- + offset[0] * final_axis1[j]
246
- + offset[1] * final_axis2[j]
247
- + offset[2] * final_axis3[j];
248
- if (repeat_mode == "MIRROR") {
258
+ final_point[j] =
259
+ point[j] +
260
+ offset[0] * final_axis1[j] +
261
+ offset[1] * final_axis2[j] +
262
+ offset[2] * final_axis3[j];
263
+ if (repeat_mode == 'MIRROR') {
249
264
  mirrored_axis1[j] = -final_axis1[j];
250
265
  mirrored_axis2[j] = -final_axis2[j];
251
266
  mirrored_axis3[j] = -final_axis3[j];
@@ -258,47 +273,48 @@ const Glyphset = function () {
258
273
  }
259
274
  }
260
275
  /* if required, reverse axis3 to maintain right-handed coordinate system */
261
- if (0.0 > (
262
- final_axis3[0] * (final_axis1[1] * final_axis2[2] -
263
- final_axis1[2] * final_axis2[1]) +
264
- final_axis3[1] * (final_axis1[2] * final_axis2[0] -
265
- final_axis1[0] * final_axis2[2]) +
266
- final_axis3[2] * (final_axis1[0] * final_axis2[1] -
267
- final_axis1[1] * final_axis2[0]))) {
276
+ if (
277
+ 0.0 >
278
+ final_axis3[0] * (final_axis1[1] * final_axis2[2] - final_axis1[2] * final_axis2[1]) +
279
+ final_axis3[1] * (final_axis1[2] * final_axis2[0] - final_axis1[0] * final_axis2[2]) +
280
+ final_axis3[2] * (final_axis1[0] * final_axis2[1] - final_axis1[1] * final_axis2[0])
281
+ ) {
268
282
  final_axis3[0] = -final_axis3[0];
269
283
  final_axis3[1] = -final_axis3[1];
270
284
  final_axis3[2] = -final_axis3[2];
271
285
  }
272
286
  return_arrays[0] = [final_point, final_axis1, final_axis2, final_axis3];
273
- if (repeat_mode == "MIRROR") {
274
- if (0.0 > (
275
- mirrored_axis3[0] * (mirrored_axis1[1] * mirrored_axis2[2] -
276
- mirrored_axis1[2] * mirrored_axis2[1]) +
277
- mirrored_axis3[1] * (mirrored_axis1[2] * mirrored_axis2[0] -
278
- mirrored_axis1[0] * mirrored_axis2[2]) +
279
- mirrored_axis3[2] * (mirrored_axis1[0] * mirrored_axis2[1] -
280
- mirrored_axis1[1] * mirrored_axis2[0]))) {
287
+ if (repeat_mode == 'MIRROR') {
288
+ if (
289
+ 0.0 >
290
+ mirrored_axis3[0] *
291
+ (mirrored_axis1[1] * mirrored_axis2[2] - mirrored_axis1[2] * mirrored_axis2[1]) +
292
+ mirrored_axis3[1] *
293
+ (mirrored_axis1[2] * mirrored_axis2[0] - mirrored_axis1[0] * mirrored_axis2[2]) +
294
+ mirrored_axis3[2] *
295
+ (mirrored_axis1[0] * mirrored_axis2[1] - mirrored_axis1[1] * mirrored_axis2[0])
296
+ ) {
281
297
  mirrored_axis3[0] = -mirrored_axis3[0];
282
298
  mirrored_axis3[1] = -mirrored_axis3[1];
283
299
  mirrored_axis3[2] = -mirrored_axis3[2];
284
300
  }
285
301
  return_arrays[1] = [mirrored_point, mirrored_axis1, mirrored_axis2, mirrored_axis3];
286
302
  }
287
- }
288
- else if (repeat_mode == "AXES_2D" || repeat_mode == "AXES_3D") {
303
+ } else if (repeat_mode == 'AXES_2D' || repeat_mode == 'AXES_3D') {
289
304
  let axis_scale = [0.0, 0.0, 0.0];
290
305
  let final_point = [0.0, 0.0, 0.0];
291
306
  for (var j = 0; j < 3; j++) {
292
- var sign = (scale[j] < 0.0) ? -1.0 : 1.0;
307
+ var sign = scale[j] < 0.0 ? -1.0 : 1.0;
293
308
  axis_scale[j] = (sign * baseSize[0] + scale[j] * scaleFactors[0]) * this.globalScale;
294
309
  }
295
310
  for (var j = 0; j < 3; j++) {
296
- final_point[j] = point[j]
297
- + offset[0] * axis_scale[0] * axis1[j]
298
- + offset[1] * axis_scale[1] * axis2[j]
299
- + offset[2] * axis_scale[2] * axis3[j];
311
+ final_point[j] =
312
+ point[j] +
313
+ offset[0] * axis_scale[0] * axis1[j] +
314
+ offset[1] * axis_scale[1] * axis2[j] +
315
+ offset[2] * axis_scale[2] * axis3[j];
300
316
  }
301
- const number_of_glyphs = (repeat_mode == "AXES_2D") ? 2 : 3;
317
+ const number_of_glyphs = repeat_mode == 'AXES_2D' ? 2 : 3;
302
318
  for (let k = 0; k < number_of_glyphs; k++) {
303
319
  let use_axis1, use_axis2;
304
320
  const use_scale = scale[k];
@@ -308,12 +324,10 @@ const Glyphset = function () {
308
324
  if (k == 0) {
309
325
  use_axis1 = axis1;
310
326
  use_axis2 = axis2;
311
- }
312
- else if (k == 1) {
327
+ } else if (k == 1) {
313
328
  use_axis1 = axis2;
314
- use_axis2 = (repeat_mode == "AXES_2D") ? axis1 : axis3;
315
- }
316
- else // if (k == 2)
329
+ use_axis2 = repeat_mode == 'AXES_2D' ? axis1 : axis3;
330
+ } else // if (k == 2)
317
331
  {
318
332
  use_axis1 = axis3;
319
333
  use_axis2 = axis1;
@@ -325,10 +339,15 @@ const Glyphset = function () {
325
339
  final_axis3[0] = final_axis1[1] * use_axis2[2] - use_axis2[1] * final_axis1[2];
326
340
  final_axis3[1] = final_axis1[2] * use_axis2[0] - use_axis2[2] * final_axis1[0];
327
341
  final_axis3[2] = final_axis1[0] * use_axis2[1] - final_axis1[1] * use_axis2[0];
328
- let magnitude = Math.sqrt(final_axis3[0] * final_axis3[0] + final_axis3[1] * final_axis3[1] + final_axis3[2] * final_axis3[2]);
342
+ let magnitude = Math.sqrt(
343
+ final_axis3[0] * final_axis3[0] +
344
+ final_axis3[1] * final_axis3[1] +
345
+ final_axis3[2] * final_axis3[2],
346
+ );
329
347
  if (0.0 < magnitude) {
330
- let scaling = (baseSize[2] + use_scale * scaleFactors[2]) * this.globalScale / magnitude;
331
- if ((repeat_mode == "AXES_2D") && (k > 0)) {
348
+ let scaling =
349
+ ((baseSize[2] + use_scale * scaleFactors[2]) * this.globalScale) / magnitude;
350
+ if (repeat_mode == 'AXES_2D' && k > 0) {
332
351
  scaling *= -1.0;
333
352
  }
334
353
  final_axis3[0] *= scaling;
@@ -339,9 +358,14 @@ const Glyphset = function () {
339
358
  final_axis2[0] = final_axis3[1] * final_axis1[2] - final_axis1[1] * final_axis3[2];
340
359
  final_axis2[1] = final_axis3[2] * final_axis1[0] - final_axis1[2] * final_axis3[0];
341
360
  final_axis2[2] = final_axis3[0] * final_axis1[1] - final_axis3[1] * final_axis1[0];
342
- magnitude = Math.sqrt(final_axis2[0] * final_axis2[0] + final_axis2[1] * final_axis2[1] + final_axis2[2] * final_axis2[2]);
361
+ magnitude = Math.sqrt(
362
+ final_axis2[0] * final_axis2[0] +
363
+ final_axis2[1] * final_axis2[1] +
364
+ final_axis2[2] * final_axis2[2],
365
+ );
343
366
  if (0.0 < magnitude) {
344
- var scaling = (baseSize[1] + use_scale * scaleFactors[1]) * this.globalScale / magnitude;
367
+ var scaling =
368
+ ((baseSize[1] + use_scale * scaleFactors[1]) * this.globalScale) / magnitude;
345
369
  final_axis2[0] *= scaling;
346
370
  final_axis2[1] *= scaling;
347
371
  final_axis2[2] *= scaling;
@@ -360,38 +384,56 @@ const Glyphset = function () {
360
384
  current_axis1s,
361
385
  current_axis2s,
362
386
  current_axis3s,
363
- current_scales
387
+ current_scales,
364
388
  ) => {
365
389
  let numberOfGlyphs = 1;
366
- if (repeat_mode == "AXES_2D" || repeat_mode == "MIRROR")
367
- numberOfGlyphs = 2;
368
- else if (repeat_mode == "AXES_3D")
369
- numberOfGlyphs = 3;
390
+ if (repeat_mode == 'AXES_2D' || repeat_mode == 'MIRROR') numberOfGlyphs = 2;
391
+ else if (repeat_mode == 'AXES_3D') numberOfGlyphs = 3;
370
392
  const numberOfPositions = current_positions.length / 3;
371
393
  let current_glyph_index = 0;
372
394
  _glyph_axis_array.length = numberOfGlyphs;
373
395
  for (let i = 0; i < numberOfPositions; i++) {
374
396
  const current_index = i * 3;
375
- const current_position = [current_positions[current_index], current_positions[current_index + 1],
376
- current_positions[current_index + 2]];
377
- const current_axis1 = [current_axis1s[current_index], current_axis1s[current_index + 1],
378
- current_axis1s[current_index + 2]];
379
- const current_axis2 = [current_axis2s[current_index], current_axis2s[current_index + 1],
380
- current_axis2s[current_index + 2]];
381
- const current_axis3 = [current_axis3s[current_index], current_axis3s[current_index + 1],
382
- current_axis3s[current_index + 2]];
383
- const current_scale = [current_scales[current_index], current_scales[current_index + 1],
384
- current_scales[current_index + 2]];
385
- const arrays = resolve_glyph_axes(current_position, current_axis1, current_axis2,
386
- current_axis3, current_scale, _glyph_axis_array);
397
+ const current_position = [
398
+ current_positions[current_index],
399
+ current_positions[current_index + 1],
400
+ current_positions[current_index + 2],
401
+ ];
402
+ const current_axis1 = [
403
+ current_axis1s[current_index],
404
+ current_axis1s[current_index + 1],
405
+ current_axis1s[current_index + 2],
406
+ ];
407
+ const current_axis2 = [
408
+ current_axis2s[current_index],
409
+ current_axis2s[current_index + 1],
410
+ current_axis2s[current_index + 2],
411
+ ];
412
+ const current_axis3 = [
413
+ current_axis3s[current_index],
414
+ current_axis3s[current_index + 1],
415
+ current_axis3s[current_index + 2],
416
+ ];
417
+ const current_scale = [
418
+ current_scales[current_index],
419
+ current_scales[current_index + 1],
420
+ current_scales[current_index + 2],
421
+ ];
422
+ const arrays = resolve_glyph_axes(
423
+ current_position,
424
+ current_axis1,
425
+ current_axis2,
426
+ current_axis3,
427
+ current_scale,
428
+ _glyph_axis_array,
429
+ );
387
430
  if (arrays.length == numberOfGlyphs) {
388
431
  for (let j = 0; j < numberOfGlyphs; j++) {
389
432
  writeTransformMatrix(_transformMatrix, arrays[j]);
390
433
  this.morph.setMatrixAt(current_glyph_index, _transformMatrix);
391
434
  const glyph = glyphList[current_glyph_index];
392
435
  if (glyph) {
393
- glyph.setTransformation(arrays[j][0], arrays[j][1],
394
- arrays[j][2], arrays[j][3]);
436
+ glyph.setTransformation(arrays[j][0], arrays[j][1], arrays[j][2], arrays[j][3]);
395
437
  }
396
438
  current_glyph_index++;
397
439
  }
@@ -418,22 +460,19 @@ const Glyphset = function () {
418
460
  */
419
461
  const updateGlyphsetHexColors = (current_colors, labelsOnly) => {
420
462
  let numberOfGlyphs = 1;
421
- if (repeat_mode == "AXES_2D" || repeat_mode == "MIRROR")
422
- numberOfGlyphs = 2;
423
- else if (repeat_mode == "AXES_3D")
424
- numberOfGlyphs = 3;
463
+ if (repeat_mode == 'AXES_2D' || repeat_mode == 'MIRROR') numberOfGlyphs = 2;
464
+ else if (repeat_mode == 'AXES_3D') numberOfGlyphs = 3;
425
465
  const numberOfColours = current_colors.length;
426
466
  let current_glyph_index = 0;
427
467
  for (let i = 0; i < numberOfColours; i++) {
428
468
  const hex_values = current_colors[i];
429
469
  for (let j = 0; j < numberOfGlyphs; j++) {
430
- _bot_colour.setHex(hex_values)
470
+ _bot_colour.setHex(hex_values);
431
471
  if (!labelsOnly) {
432
472
  this.morph.setColorAt(current_glyph_index, _bot_colour);
433
473
  }
434
474
  const glyph = glyphList[current_glyph_index];
435
- if (glyph)
436
- glyph.setColour(_bot_colour);
475
+ if (glyph) glyph.setColour(_bot_colour);
437
476
  current_glyph_index++;
438
477
  }
439
478
  }
@@ -531,17 +570,19 @@ const Glyphset = function () {
531
570
  glyphCompute.uniforms.globalScale.value = this.globalScale;
532
571
  glyphComputePending = true;
533
572
  boundsAreExact = false;
534
- dispatchAndReadbackGlyphTransform(renderer, glyphCompute).then((result) => {
535
- glyphComputePending = false;
536
- applyGlyphComputeResult(result);
537
- boundsAreExact = true;
538
- // Restore the stock InstancedMesh.raycast (instanceMatrix is now
539
- // exact again) by dropping the no-op instance override, if present.
540
- delete this.morph.raycast;
541
- }).catch((err) => {
542
- glyphComputePending = false;
543
- console.error("Glyph transform compute readback failed.", err);
544
- });
573
+ dispatchAndReadbackGlyphTransform(renderer, glyphCompute)
574
+ .then((result) => {
575
+ glyphComputePending = false;
576
+ applyGlyphComputeResult(result);
577
+ boundsAreExact = true;
578
+ // Restore the stock InstancedMesh.raycast (instanceMatrix is now
579
+ // exact again) by dropping the no-op instance override, if present.
580
+ delete this.morph.raycast;
581
+ })
582
+ .catch((err) => {
583
+ glyphComputePending = false;
584
+ console.error('Glyph transform compute readback failed.', err);
585
+ });
545
586
  };
546
587
 
547
588
  /**
@@ -576,15 +617,17 @@ const Glyphset = function () {
576
617
  const renderer = this.region?.getScene?.()?.getRenderer?.();
577
618
  if (!renderer) return;
578
619
  glyphComputePending = true;
579
- readbackGlyphTransform(renderer, glyphCompute).then((result) => {
580
- glyphComputePending = false;
581
- applyGlyphComputeResult(result);
582
- boundsAreExact = true;
583
- delete this.morph.raycast;
584
- }).catch((err) => {
585
- glyphComputePending = false;
586
- console.error("Glyph transform compute readback failed.", err);
587
- });
620
+ readbackGlyphTransform(renderer, glyphCompute)
621
+ .then((result) => {
622
+ glyphComputePending = false;
623
+ applyGlyphComputeResult(result);
624
+ boundsAreExact = true;
625
+ delete this.morph.raycast;
626
+ })
627
+ .catch((err) => {
628
+ glyphComputePending = false;
629
+ console.error('Glyph transform compute readback failed.', err);
630
+ });
588
631
  };
589
632
 
590
633
  const cancelScheduledAccurateResync = () => {
@@ -618,7 +661,7 @@ const Glyphset = function () {
618
661
  * immediately, as before.
619
662
  */
620
663
  const updateMorphGlyphsets = (debounceAccurateResync) => {
621
- const current_time = this.inbuildTime / this.duration * (numberOfTimeSteps - 1);
664
+ const current_time = (this.inbuildTime / this.duration) * (numberOfTimeSteps - 1);
622
665
  const bottom_frame = Math.floor(current_time);
623
666
  const proportion = 1 - (current_time - bottom_frame);
624
667
  const top_frame = Math.ceil(current_time);
@@ -662,24 +705,30 @@ const Glyphset = function () {
662
705
  _current_scales.length = bottom_positions.length;
663
706
 
664
707
  for (let i = 0; i < bottom_positions.length; i++) {
665
- current_positions[i] = proportion * bottom_positions[i] + (1.0 - proportion) * top_positions[i];
708
+ current_positions[i] =
709
+ proportion * bottom_positions[i] + (1.0 - proportion) * top_positions[i];
666
710
  current_axis1s[i] = proportion * bottom_axis1[i] + (1.0 - proportion) * top_axis1[i];
667
711
  current_axis2s[i] = proportion * bottom_axis2[i] + (1.0 - proportion) * top_axis2[i];
668
712
  current_axis3s[i] = proportion * bottom_axis3[i] + (1.0 - proportion) * top_axis3[i];
669
713
  current_scales[i] = proportion * bottom_scale[i] + (1.0 - proportion) * top_scale[i];
670
714
  }
671
715
  } else {
672
- current_positions = positions["0"];
673
- current_axis1s = axis1s["0"];
674
- current_axis2s = axis2s["0"];
675
- current_axis3s = axis3s["0"];
676
- current_scales = scales["0"];
716
+ current_positions = positions['0'];
717
+ current_axis1s = axis1s['0'];
718
+ current_axis2s = axis2s['0'];
719
+ current_axis3s = axis3s['0'];
720
+ current_scales = scales['0'];
677
721
  }
678
722
  //Colour only morphing does not change the transformation, skip it
679
723
  //unless it is out of date.
680
724
  if (morphVertices || !staticTransformationApplied) {
681
- updateGlyphsetTransformation(current_positions, current_axis1s, current_axis2s, current_axis3s,
682
- current_scales);
725
+ updateGlyphsetTransformation(
726
+ current_positions,
727
+ current_axis1s,
728
+ current_axis2s,
729
+ current_axis3s,
730
+ current_scales,
731
+ );
683
732
  staticTransformationApplied = !morphVertices;
684
733
  }
685
734
  if (colors != undefined) {
@@ -690,13 +739,15 @@ const Glyphset = function () {
690
739
  for (let i = 0; i < bottom_colors.length; i++) {
691
740
  _bot_colour.setHex(bottom_colors[i]);
692
741
  _top_colour.setHex(top_colors[i]);
693
- _bot_colour.setRGB(_bot_colour.r * proportion + _top_colour.r * (1 - proportion),
742
+ _bot_colour.setRGB(
743
+ _bot_colour.r * proportion + _top_colour.r * (1 - proportion),
694
744
  _bot_colour.g * proportion + _top_colour.g * (1 - proportion),
695
- _bot_colour.b * proportion + _top_colour.b * (1 - proportion));
745
+ _bot_colour.b * proportion + _top_colour.b * (1 - proportion),
746
+ );
696
747
  current_colors[i] = _bot_colour.getHex();
697
748
  }
698
749
  } else {
699
- current_colors = colors["0"];
750
+ current_colors = colors['0'];
700
751
  }
701
752
  updateGlyphsetHexColors(current_colors, false);
702
753
  }
@@ -709,7 +760,7 @@ const Glyphset = function () {
709
760
  */
710
761
  this.isUsingGPUCompute = () => {
711
762
  return glyphCompute !== undefined;
712
- }
763
+ };
713
764
 
714
765
  /**
715
766
  * Get the assigned label for instance at index
@@ -719,18 +770,18 @@ const Glyphset = function () {
719
770
  return labels[index];
720
771
  }
721
772
  return undefined;
722
- }
773
+ };
723
774
 
724
775
  this.isLabelDisplayed = () => {
725
776
  return labelsOn;
726
- }
777
+ };
727
778
 
728
779
  /**
729
780
  * Check whether label can be shown
730
781
  */
731
782
  this.canShowLabel = () => {
732
- return (glyphList?.length && (labels?.length || this.groupName));
733
- }
783
+ return glyphList?.length && (labels?.length || this.groupName);
784
+ };
734
785
 
735
786
  /**
736
787
  * Display the label of the glyphs in the glyphset.
@@ -743,18 +794,18 @@ const Glyphset = function () {
743
794
  glyphList[i].showLabel(this.morph.material ? this.morph.material.color : undefined);
744
795
  }
745
796
  }
746
- }
797
+ };
747
798
 
748
799
  /**
749
800
  * Hide label with the choosen colour.
750
801
  */
751
- this.hideLabel = () => {
752
- this.requestRender();
753
- for (let i = 0; i < glyphList.length; i++) {
754
- glyphList[i].hideLabel();
755
- }
756
- labelsOn = false;
802
+ this.hideLabel = () => {
803
+ this.requestRender();
804
+ for (let i = 0; i < glyphList.length; i++) {
805
+ glyphList[i].hideLabel();
757
806
  }
807
+ labelsOn = false;
808
+ };
758
809
 
759
810
  /**
760
811
  * Computes a single Box3 that conservatively contains every keyframe's
@@ -801,7 +852,7 @@ const Glyphset = function () {
801
852
  }
802
853
  }
803
854
  return first ? undefined : result;
804
- }
855
+ };
805
856
 
806
857
  /**
807
858
  * Create the glyphs in the glyphset.
@@ -827,11 +878,16 @@ const Glyphset = function () {
827
878
  this.showLabel();
828
879
  }
829
880
  //Update the transformation of the glyphs.
830
- updateGlyphsetTransformation(positions["0"], axis1s["0"],
831
- axis2s["0"], axis3s["0"], scales["0"]);
881
+ updateGlyphsetTransformation(
882
+ positions['0'],
883
+ axis1s['0'],
884
+ axis2s['0'],
885
+ axis3s['0'],
886
+ scales['0'],
887
+ );
832
888
  staticTransformationApplied = true;
833
889
  if (colors != undefined) {
834
- updateGlyphsetHexColors(colors["0"], !!(glyphCompute && glyphCompute.outputs.color));
890
+ updateGlyphsetHexColors(colors['0'], !!(glyphCompute && glyphCompute.outputs.color));
835
891
  }
836
892
  if (glyphCompute) {
837
893
  allFramesBoundingBox = computeAllFramesBoundingBox();
@@ -844,13 +900,12 @@ const Glyphset = function () {
844
900
  *
845
901
  * @param {Glyph} Glyph to be added.
846
902
  */
847
- this.addCustomGlyph = glyph => {
903
+ this.addCustomGlyph = (glyph) => {
848
904
  this.requestRender();
849
- if (glyph.isGlyph)
850
- glyphList.push(glyph);
905
+ if (glyph.isGlyph) glyphList.push(glyph);
851
906
  this.ready = true;
852
907
  this.boundingBoxUpdateRequired = true;
853
- }
908
+ };
854
909
 
855
910
  /**
856
911
  * Add a THREE.Mesh object to be displayed as glyph in this {@link Glyphset}.
@@ -864,13 +919,13 @@ const Glyphset = function () {
864
919
  const glyph = new Glyph(undefined, undefined, id, this);
865
920
  glyph.fromMesh(mesh);
866
921
  glyphList.push(glyph);
867
- this.morph.add(glyph.getGroup())
922
+ this.morph.add(glyph.getGroup());
868
923
  this.ready = true;
869
924
  this.boundingBoxUpdateRequired = true;
870
925
  return glyph;
871
926
  }
872
927
  return undefined;
873
- }
928
+ };
874
929
 
875
930
  /**
876
931
  * A function which iterates through the list of glyphs and call the callback
@@ -879,11 +934,11 @@ const Glyphset = function () {
879
934
  * @param {Function} callbackFunction - Callback function with the glyph
880
935
  * as an argument.
881
936
  */
882
- this.forEachGlyph = callbackFunction => {
937
+ this.forEachGlyph = (callbackFunction) => {
883
938
  for (let i = 0; i < glyphList.length; i++) {
884
939
  callbackFunction(glyphList[i]);
885
940
  }
886
- }
941
+ };
887
942
 
888
943
  var meshloader = (finishCallback, displayLabels) => {
889
944
  return (geometry, materials) => {
@@ -894,8 +949,7 @@ const Glyphset = function () {
894
949
  this.geometry.copy(geometry);
895
950
  this.geometry.computeBoundingSphere();
896
951
  this.geometry.computeBoundingBox();
897
- if (materials && materials[0])
898
- this.morph.material = materials[0];
952
+ if (materials && materials[0]) this.morph.material = materials[0];
899
953
  if (glyphCompute) {
900
954
  this.morph.material = createGlyphInstancedMaterial(this.morph.material, glyphCompute);
901
955
  }
@@ -904,27 +958,28 @@ const Glyphset = function () {
904
958
  this.morph.userData = this;
905
959
  this.setMorph(this.morph);
906
960
  geometry.dispose();
907
- if (finishCallback != undefined && (typeof finishCallback == 'function'))
908
- finishCallback(this);
961
+ if (finishCallback != undefined && typeof finishCallback == 'function') finishCallback(this);
909
962
  };
910
- }
963
+ };
911
964
 
912
965
  /**
913
- * Get the index of the closest vertex to centroid.
914
- */
966
+ * Get the index of the closest vertex to centroid.
967
+ */
915
968
  this.getClosestVertexIndex = function () {
916
969
  let closestIndex = -1;
917
970
  if (this.morph && this.ready) {
918
971
  this.getBoundingBox().getCenter(this._v1);
919
- let current_positions = positions["0"];
972
+ let current_positions = positions['0'];
920
973
  const numberOfPositions = current_positions.length / 3;
921
974
  let distance = -1;
922
975
  let currentDistance = 0;
923
976
  for (let i = 0; i < numberOfPositions; i++) {
924
977
  const current_index = i * 3;
925
- this._v2.set(current_positions[current_index],
978
+ this._v2.set(
979
+ current_positions[current_index],
926
980
  current_positions[current_index + 1],
927
- current_positions[current_index + 2]);
981
+ current_positions[current_index + 2],
982
+ );
928
983
  currentDistance = this._v1.distanceTo(this._v2);
929
984
  if (distance == -1) {
930
985
  distance = currentDistance;
@@ -936,13 +991,12 @@ const Glyphset = function () {
936
991
  }
937
992
  }
938
993
  return closestIndex;
939
- }
994
+ };
940
995
 
941
996
  /**
942
997
  * Get the closest vertex to centroid.
943
998
  */
944
999
  this.getClosestVertex = function () {
945
-
946
1000
  if (this.closestVertexIndex == -1) {
947
1001
  this.closestVertexIndex = this.getClosestVertexIndex();
948
1002
  }
@@ -961,7 +1015,7 @@ const Glyphset = function () {
961
1015
  }
962
1016
 
963
1017
  return undefined;
964
- }
1018
+ };
965
1019
 
966
1020
  /**
967
1021
  * Get the bounding box for the whole set of glyphs.
@@ -976,8 +1030,7 @@ const Glyphset = function () {
976
1030
  return this.cachedBoundingBox;
977
1031
  }
978
1032
  if (this.boundingBoxUpdateRequired) {
979
- _boundingBox1.setFromBufferAttribute(
980
- this.morph.geometry.attributes.position);
1033
+ _boundingBox1.setFromBufferAttribute(this.morph.geometry.attributes.position);
981
1034
  for (let i = 0; i < numberOfVertices; i++) {
982
1035
  this.morph.getMatrixAt(i, _transformMatrix);
983
1036
  _boundingBox2.copy(_boundingBox1).applyMatrix4(_transformMatrix);
@@ -991,33 +1044,28 @@ const Glyphset = function () {
991
1044
  this.cachedBoundingBox.copy(_boundingBox3);
992
1045
  this.cachedBoundingBox.applyMatrix4(updateWorldMatrixFromAncestors(this.morph));
993
1046
  this.boundingBoxUpdateRequired = false;
994
- } else
995
- return undefined;
1047
+ } else return undefined;
996
1048
  }
997
1049
  return this.cachedBoundingBox;
998
1050
  }
999
1051
  return undefined;
1000
- }
1052
+ };
1001
1053
 
1002
1054
  /**
1003
1055
  * Set the local time of this glyphset.
1004
1056
  *
1005
1057
  * @param {Number} time - Can be any value between 0 to duration.
1006
1058
  */
1007
- this.setMorphTime = time => {
1059
+ this.setMorphTime = (time) => {
1008
1060
  this.requestRender();
1009
- if (time > this.duration)
1010
- this.inbuildTime = this.duration;
1011
- else if (0 > time)
1012
- this.inbuildTime = 0;
1013
- else
1014
- this.inbuildTime = time;
1061
+ if (time > this.duration) this.inbuildTime = this.duration;
1062
+ else if (0 > time) this.inbuildTime = 0;
1063
+ else this.inbuildTime = time;
1015
1064
  if (morphColours || morphVertices) {
1016
1065
  updateMorphGlyphsets(true);
1017
- if (morphVertices)
1018
- this.markerUpdateRequired = true;
1066
+ if (morphVertices) this.markerUpdateRequired = true;
1019
1067
  }
1020
- }
1068
+ };
1021
1069
 
1022
1070
  /**
1023
1071
  * Check if the glyphset is time varying.
@@ -1025,11 +1073,10 @@ const Glyphset = function () {
1025
1073
  * @return {Boolean}
1026
1074
  */
1027
1075
  this.isTimeVarying = () => {
1028
- if (((this.ready === false) || (numberOfTimeSteps > 0)) &&
1029
- (morphColours || morphVertices))
1076
+ if ((this.ready === false || numberOfTimeSteps > 0) && (morphColours || morphVertices))
1030
1077
  return true;
1031
1078
  return false;
1032
- }
1079
+ };
1033
1080
 
1034
1081
  /**
1035
1082
  * Get the current inbuild time of the
@@ -1038,7 +1085,7 @@ const Glyphset = function () {
1038
1085
  */
1039
1086
  this.getCurrentTime = () => {
1040
1087
  return this.inbuildTime;
1041
- }
1088
+ };
1042
1089
 
1043
1090
  /**
1044
1091
  * Exporters (see sceneExporter.js/GLTFExporter.js) read
@@ -1068,7 +1115,7 @@ const Glyphset = function () {
1068
1115
  colorArray[o3 + 2] = colorResult[o4 + 2];
1069
1116
  }
1070
1117
  this.morph.instanceColor.needsUpdate = true;
1071
- }
1118
+ };
1072
1119
 
1073
1120
  /**
1074
1121
  * Undoes prepareColorForExport() - see its comment for why this matters:
@@ -1080,19 +1127,19 @@ const Glyphset = function () {
1080
1127
  this.morph.instanceColor = null;
1081
1128
  if (this.morph.material) this.morph.material.needsUpdate = true;
1082
1129
  }
1083
- }
1130
+ };
1084
1131
 
1085
1132
  /**
1086
1133
  * Set the objects scale.
1087
1134
  *
1088
1135
  * @return {THREE.Box3}.
1089
1136
  */
1090
- this.setScaleAll = function(scale) {
1137
+ this.setScaleAll = function (scale) {
1091
1138
  this.requestRender();
1092
1139
  this.globalScale = scale;
1093
1140
  staticTransformationApplied = false;
1094
1141
  updateMorphGlyphsets(false);
1095
- }
1142
+ };
1096
1143
 
1097
1144
  /**
1098
1145
  * Clear this glyphset and its list of glyphs which will release them from the memory.
@@ -1102,10 +1149,8 @@ const Glyphset = function () {
1102
1149
  for (let i = glyphList.length - 1; i >= 0; i--) {
1103
1150
  glyphList[i].dispose();
1104
1151
  }
1105
- if (this.geometry)
1106
- this.geometry.dispose();
1107
- if (this.morph)
1108
- this.morph.material.dispose();
1152
+ if (this.geometry) this.geometry.dispose();
1153
+ if (this.morph) this.morph.material.dispose();
1109
1154
  cancelScheduledAccurateResync();
1110
1155
  axis1s = undefined;
1111
1156
  axis2s = undefined;
@@ -1121,7 +1166,7 @@ const Glyphset = function () {
1121
1166
  allFramesBoundingBox = undefined;
1122
1167
  this.ready = false;
1123
1168
  this.groupName = undefined;
1124
- }
1169
+ };
1125
1170
 
1126
1171
  /**
1127
1172
  * Update the glyphsets if required the render.
@@ -1137,8 +1182,7 @@ const Glyphset = function () {
1137
1182
  }
1138
1183
  if (playAnimation == true) {
1139
1184
  let targetTime = this.inbuildTime + delta;
1140
- if (targetTime > this.duration)
1141
- targetTime = targetTime - this.duration;
1185
+ if (targetTime > this.duration) targetTime = targetTime - this.duration;
1142
1186
  this.inbuildTime = targetTime;
1143
1187
  if (morphVertices && glyphCompute) {
1144
1188
  // Fast GPU-only path: update the render buffers every frame with
@@ -1148,7 +1192,7 @@ const Glyphset = function () {
1148
1192
  // downstream slider) left debounced-and-pending - it would apply a
1149
1193
  // now-stale frame once it fired mid-animation otherwise.
1150
1194
  cancelScheduledAccurateResync();
1151
- const current_time = this.inbuildTime / this.duration * (numberOfTimeSteps - 1);
1195
+ const current_time = (this.inbuildTime / this.duration) * (numberOfTimeSteps - 1);
1152
1196
  const bottom_frame = Math.floor(current_time);
1153
1197
  const proportion = 1 - (current_time - bottom_frame);
1154
1198
  const top_frame = Math.ceil(current_time);
@@ -1166,8 +1210,8 @@ const Glyphset = function () {
1166
1210
  wasAnimating = false;
1167
1211
  }
1168
1212
  this.updateMarker(playAnimation, options);
1169
- }
1170
- }
1213
+ };
1214
+ };
1171
1215
 
1172
1216
  Glyphset.prototype = Object.create(ZincObject.prototype);
1173
1217
  export { Glyphset };