@kitware/vtk.js 33.0.0-beta.2 → 33.0.0-beta.4

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 (87) hide show
  1. package/Common/Core/DataArray.d.ts +21 -0
  2. package/Common/Core/DataArray.js +39 -0
  3. package/Common/Core/Math/index.js +1 -1
  4. package/Common/Core/Math.js +1 -1
  5. package/Common/Core/URLExtract.js +2 -6
  6. package/Common/DataModel/Line.js +1 -0
  7. package/Common/DataModel/PolyLine.js +4 -0
  8. package/Filters/Core/ThresholdPoints.d.ts +72 -0
  9. package/Filters/Core/ThresholdPoints.js +219 -0
  10. package/Filters/General/ContourTriangulator/helper.js +1 -1
  11. package/IO/Core/DataAccessHelper/JSZipDataAccessHelper.js +1 -1
  12. package/IO/Geometry/DracoReader.d.ts +4 -4
  13. package/IO/Geometry/DracoReader.js +154 -105
  14. package/IO/Geometry/GLTFImporter/Animations.js +239 -0
  15. package/IO/Geometry/GLTFImporter/Constants.js +87 -0
  16. package/IO/Geometry/GLTFImporter/Decoder.js +69 -0
  17. package/IO/Geometry/GLTFImporter/Extensions.js +110 -0
  18. package/IO/Geometry/GLTFImporter/ORMTexture.worker.js +42 -0
  19. package/IO/Geometry/GLTFImporter/Parser.js +359 -0
  20. package/IO/Geometry/GLTFImporter/Reader.js +518 -0
  21. package/IO/Geometry/GLTFImporter/Utils.js +165 -0
  22. package/IO/Geometry/GLTFImporter.d.ts +266 -0
  23. package/IO/Geometry/GLTFImporter.js +245 -0
  24. package/IO/Geometry/IFCImporter.d.ts +163 -0
  25. package/IO/Geometry/IFCImporter.js +270 -0
  26. package/IO/Geometry/STLReader.d.ts +14 -0
  27. package/IO/Geometry/STLReader.js +57 -1
  28. package/IO/Geometry.js +5 -1
  29. package/IO/Image/HDRReader/Utils.js +1 -1
  30. package/IO/Image/HDRReader.js +1 -1
  31. package/IO/Image/TGAReader/Constants.js +28 -0
  32. package/IO/Image/TGAReader.d.ts +121 -0
  33. package/IO/Image/TGAReader.js +418 -0
  34. package/IO/Image/TIFFReader.d.ts +133 -0
  35. package/IO/Image/TIFFReader.js +144 -0
  36. package/IO/Image.js +5 -1
  37. package/IO/XML/XMLPolyDataWriter.js +1 -0
  38. package/Interaction/Manipulators/MouseCameraTrackballRollManipulator.js +1 -1
  39. package/Interaction/Style/InteractorStyleTrackballCamera.js +1 -1
  40. package/Rendering/Core/AbstractImageMapper.d.ts +81 -0
  41. package/Rendering/Core/AbstractImageMapper.js +5 -2
  42. package/Rendering/Core/AbstractPicker.d.ts +13 -13
  43. package/Rendering/Core/AbstractPicker.js +1 -1
  44. package/Rendering/Core/Actor2D.d.ts +22 -0
  45. package/Rendering/Core/Actor2D.js +1 -1
  46. package/Rendering/Core/CellPicker.js +4 -1
  47. package/Rendering/Core/Glyph3DMapper.d.ts +45 -29
  48. package/Rendering/Core/ImageCPRMapper.js +6 -5
  49. package/Rendering/Core/ImageProperty.d.ts +42 -1
  50. package/Rendering/Core/ImageProperty.js +7 -5
  51. package/Rendering/Core/ImageResliceMapper.d.ts +1 -2
  52. package/Rendering/Core/ImageResliceMapper.js +5 -4
  53. package/Rendering/Core/PointPicker.js +10 -1
  54. package/Rendering/Core/Prop3D.js +1 -1
  55. package/Rendering/Core/RenderWindowInteractor.d.ts +1 -1
  56. package/Rendering/Core/RenderWindowInteractor.js +1 -1
  57. package/Rendering/Core/Viewport.js +13 -3
  58. package/Rendering/Core/VolumeMapper.d.ts +70 -0
  59. package/Rendering/Core/VolumeMapper.js +10 -5
  60. package/Rendering/Core/VolumeProperty.d.ts +20 -1
  61. package/Rendering/Core/VolumeProperty.js +7 -5
  62. package/Rendering/Misc/CanvasView.js +4 -2
  63. package/Rendering/Misc/RemoteView.d.ts +9 -3
  64. package/Rendering/Misc/RemoteView.js +7 -3
  65. package/Rendering/Misc/SynchronizableRenderWindow/BehaviorManager/CameraSynchronizer.js +2 -2
  66. package/Rendering/Misc/SynchronizableRenderWindow/ObjectManager.d.ts +1 -1
  67. package/Rendering/OpenGL/ImageCPRMapper.js +18 -2
  68. package/Rendering/OpenGL/ImageMapper.js +42 -11
  69. package/Rendering/OpenGL/ImageResliceMapper.js +20 -4
  70. package/Rendering/OpenGL/Renderer.js +1 -1
  71. package/Rendering/OpenGL/Texture/supportsNorm16Linear.js +97 -0
  72. package/Rendering/OpenGL/Texture.d.ts +29 -8
  73. package/Rendering/OpenGL/Texture.js +172 -34
  74. package/Rendering/OpenGL/VolumeMapper.js +22 -4
  75. package/Rendering/SceneGraph/ViewNode.js +12 -2
  76. package/Rendering/WebXR/RenderWindowHelper.js +9 -0
  77. package/Widgets/Core/WidgetManager.d.ts +12 -1
  78. package/Widgets/Representations/WidgetRepresentation.d.ts +1 -7
  79. package/Widgets/Widgets3D/AngleWidget/behavior.js +2 -0
  80. package/Widgets/Widgets3D/InteractiveOrientationWidget.js +1 -1
  81. package/Widgets/Widgets3D/ResliceCursorWidget/behavior.js +17 -0
  82. package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -0
  83. package/Widgets/Widgets3D/ResliceCursorWidget.d.ts +1 -8
  84. package/Widgets/Widgets3D/ShapeWidget/behavior.js +3 -0
  85. package/_virtual/rollup-plugin-worker-loader__module_Sources/IO/Geometry/GLTFImporter/ORMTexture.worker.js +296 -0
  86. package/index.d.ts +5 -0
  87. package/package.json +19 -17
@@ -1,9 +1,9 @@
1
1
  import { Wrap, Filter } from './Texture/Constants';
2
2
  import vtkOpenGLRenderWindow from './RenderWindow';
3
- import { Nullable } from './../../types';
3
+ import { Extent, Nullable } from './../../types';
4
4
  import { VtkDataTypes } from './../../Common/Core/DataArray';
5
5
  import { vtkViewNode } from './../SceneGraph/ViewNode';
6
- import { vtkObject } from './../../interfaces';
6
+ import { vtkObject, vtkRange } from './../../interfaces';
7
7
 
8
8
  /**
9
9
  * Initial values for creating a new instance of vtkOpenGLTexture.
@@ -244,7 +244,8 @@ export interface vtkOpenGLTexture extends vtkViewNode {
244
244
  * @param numComps The number of components in the texture.
245
245
  * @param dataType The data type of the texture.
246
246
  * @param data The raw data for the texture.
247
- * @param preferSizeOverAccuracy Whether to prefer texture size over accuracy.
247
+ * @param [preferSizeOverAccuracy=false] Whether to prefer texture size over accuracy. Defaults to false.
248
+ * @param [ranges] The precomputed ranges of the data (optional). Provided to prevent computation of the data ranges.
248
249
  * @returns {boolean} True if the texture was successfully created, false otherwise.
249
250
  */
250
251
  create2DFilterableFromRaw(
@@ -253,7 +254,8 @@ export interface vtkOpenGLTexture extends vtkViewNode {
253
254
  numComps: number,
254
255
  dataType: VtkDataTypes,
255
256
  data: any,
256
- preferSizeOverAccuracy: boolean
257
+ preferSizeOverAccuracy?: boolean,
258
+ ranges?: vtkRange[]
257
259
  ): boolean;
258
260
 
259
261
  /**
@@ -273,12 +275,16 @@ export interface vtkOpenGLTexture extends vtkViewNode {
273
275
 
274
276
  /**
275
277
  * Creates a 3D texture from raw data.
278
+ *
279
+ * updatedExtents is currently incompatible with webgl1, since there's no extent scaling.
280
+ *
276
281
  * @param width The width of the texture.
277
282
  * @param height The height of the texture.
278
283
  * @param depth The depth of the texture.
279
284
  * @param numComps The number of components in the texture.
280
285
  * @param dataType The data type of the texture.
281
286
  * @param data The raw data for the texture.
287
+ * @param updatedExtents Only update the specified extents (default: [])
282
288
  * @returns {boolean} True if the texture was successfully created, false otherwise.
283
289
  */
284
290
  create3DFromRaw(
@@ -287,11 +293,15 @@ export interface vtkOpenGLTexture extends vtkViewNode {
287
293
  depth: number,
288
294
  numComps: number,
289
295
  dataType: VtkDataTypes,
290
- data: any
296
+ data: any,
297
+ updatedExtents?: Extent[]
291
298
  ): boolean;
292
299
 
293
300
  /**
294
301
  * Creates a 3D filterable texture from raw data, with a preference for size over accuracy if necessary.
302
+ *
303
+ * updatedExtents is currently incompatible with webgl1, since there's no extent scaling.
304
+ *
295
305
  * @param width The width of the texture.
296
306
  * @param height The height of the texture.
297
307
  * @param depth The depth of the texture.
@@ -299,7 +309,11 @@ export interface vtkOpenGLTexture extends vtkViewNode {
299
309
  * @param dataType The data type of the texture.
300
310
  * @param values The raw data for the texture.
301
311
  * @param preferSizeOverAccuracy Whether to prefer texture size over accuracy.
302
- * @returns {boolean} True if the texture was successfully created, false otherwise.
312
+ * @param [ranges] The precomputed ranges of the data (optional). Provided to
313
+ * @param updatedExtents Only update the specified extents (default: [])
314
+ * prevent computation of the data ranges.
315
+ * @returns {boolean} True if the texture was successfully created, false
316
+ * otherwise.
303
317
  */
304
318
  create3DFilterableFromRaw(
305
319
  width: number,
@@ -308,16 +322,22 @@ export interface vtkOpenGLTexture extends vtkViewNode {
308
322
  numComps: number,
309
323
  dataType: VtkDataTypes,
310
324
  values: any,
311
- preferSizeOverAccuracy: boolean
325
+ preferSizeOverAccuracy: boolean,
326
+ ranges?: vtkRange[],
327
+ updatedExtents?: Extent[]
312
328
  ): boolean;
313
329
 
314
330
  /**
315
331
  * Creates a 3D filterable texture from a data array, with a preference for size over accuracy if necessary.
332
+ *
333
+ * updatedExtents is currently incompatible with webgl1, since there's no extent scaling.
334
+ *
316
335
  * @param width The width of the texture.
317
336
  * @param height The height of the texture.
318
337
  * @param depth The depth of the texture.
319
338
  * @param dataArray The data array to use for the texture.
320
339
  * @param preferSizeOverAccuracy Whether to prefer texture size over accuracy.
340
+ * @param updatedExtents Only update the specified extents (default: [])
321
341
  * @returns {boolean} True if the texture was successfully created, false otherwise.
322
342
  */
323
343
  create3DFilterableFromDataArray(
@@ -325,7 +345,8 @@ export interface vtkOpenGLTexture extends vtkViewNode {
325
345
  height: number,
326
346
  depth: number,
327
347
  dataArray: any,
328
- preferSizeOverAccuracy: boolean
348
+ preferSizeOverAccuracy: boolean,
349
+ updatedExtents?: Extent[]
329
350
  ): boolean;
330
351
 
331
352
  /**
@@ -1,3 +1,4 @@
1
+ import DeepEqual from 'fast-deep-equal';
1
2
  import Constants from './Texture/Constants.js';
2
3
  import HalfFloat from '../../Common/Core/HalfFloat.js';
3
4
  import { n as newInstance$1, o as obj, s as set, e as setGet, g as get, i as moveToProtected, a as newTypedArray, c as macro } from '../../macros2.js';
@@ -5,6 +6,7 @@ import vtkDataArray from '../../Common/Core/DataArray.js';
5
6
  import { V as isPowerOfTwo, R as nearestPowerOfTwo } from '../../Common/Core/Math/index.js';
6
7
  import vtkViewNode from '../SceneGraph/ViewNode.js';
7
8
  import { registerOverride } from './ViewNodeFactory.js';
9
+ import supportsNorm16LinearCached from './Texture/supportsNorm16Linear.js';
8
10
 
9
11
  const {
10
12
  Wrap,
@@ -29,6 +31,16 @@ const {
29
31
  function vtkOpenGLTexture(publicAPI, model) {
30
32
  // Set our className
31
33
  model.classHierarchy.push('vtkOpenGLTexture');
34
+ function getTexParams() {
35
+ return {
36
+ internalFormat: model.internalFormat,
37
+ format: model.format,
38
+ openGLDataType: model.openGLDataType,
39
+ width: model.width,
40
+ height: model.height
41
+ };
42
+ }
43
+
32
44
  // Renders myself
33
45
  publicAPI.render = function () {
34
46
  let renWin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
@@ -133,6 +145,12 @@ function vtkOpenGLTexture(publicAPI, model) {
133
145
  publicAPI.activate();
134
146
  }
135
147
  };
148
+ const getNorm16Ext = () => {
149
+ if ((model.minificationFilter === Filter.LINEAR || model.magnificationFilter === Filter.LINEAR) && !supportsNorm16LinearCached()) {
150
+ return undefined;
151
+ }
152
+ return model.oglNorm16Ext;
153
+ };
136
154
 
137
155
  //----------------------------------------------------------------------------
138
156
  publicAPI.destroyTexture = () => {
@@ -141,6 +159,7 @@ function vtkOpenGLTexture(publicAPI, model) {
141
159
  if (model.context && model.handle) {
142
160
  model.context.deleteTexture(model.handle);
143
161
  }
162
+ model._prevTexParams = null;
144
163
  model.handle = 0;
145
164
  model.numberOfDimensions = 0;
146
165
  model.target = 0;
@@ -202,6 +221,7 @@ function vtkOpenGLTexture(publicAPI, model) {
202
221
  rwin.activateTexture(publicAPI);
203
222
  rwin.deactivateTexture(publicAPI);
204
223
  model.context.deleteTexture(model.handle);
224
+ model._prevTexParams = null;
205
225
  model.handle = 0;
206
226
  model.numberOfDimensions = 0;
207
227
  model.target = 0;
@@ -285,7 +305,7 @@ function vtkOpenGLTexture(publicAPI, model) {
285
305
  publicAPI.getDefaultInternalFormat = (vtktype, numComps) => {
286
306
  let result = 0;
287
307
  // try default next
288
- result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, model.oglNorm16Ext, publicAPI.useHalfFloat());
308
+ result = model._openGLRenderWindow.getDefaultTextureInternalFormat(vtktype, numComps, getNorm16Ext(), publicAPI.useHalfFloat());
289
309
  if (result) {
290
310
  return result;
291
311
  }
@@ -346,6 +366,7 @@ function vtkOpenGLTexture(publicAPI, model) {
346
366
 
347
367
  //----------------------------------------------------------------------------
348
368
  publicAPI.resetFormatAndType = () => {
369
+ model._prevTexParams = null;
349
370
  model.format = 0;
350
371
  model.internalFormat = 0;
351
372
  model._forceInternalFormat = false;
@@ -364,9 +385,9 @@ function vtkOpenGLTexture(publicAPI, model) {
364
385
  return model.context.UNSIGNED_BYTE;
365
386
  // prefer norm16 since that is accurate compared to
366
387
  // half float which is not
367
- case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.SHORT:
388
+ case getNorm16Ext() && !useHalfFloat && VtkDataTypes.SHORT:
368
389
  return model.context.SHORT;
369
- case model.oglNorm16Ext && !useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
390
+ case getNorm16Ext() && !useHalfFloat && VtkDataTypes.UNSIGNED_SHORT:
370
391
  return model.context.UNSIGNED_SHORT;
371
392
  // use half float type
372
393
  case useHalfFloat && VtkDataTypes.SHORT:
@@ -492,6 +513,86 @@ function vtkOpenGLTexture(publicAPI, model) {
492
513
  }
493
514
  };
494
515
 
516
+ //----------------------------------------------------------------------------
517
+
518
+ /**
519
+ * Gets the extent's size.
520
+ * @param {Extent} extent
521
+ */
522
+ function getExtentSize(extent) {
523
+ const [xmin, xmax, ymin, ymax, zmin, zmax] = extent;
524
+ return [xmax - xmin + 1, ymax - ymin + 1, zmax - zmin + 1];
525
+ }
526
+
527
+ //----------------------------------------------------------------------------
528
+
529
+ /**
530
+ * Gets the number of pixels in the extent.
531
+ * @param {Extent} extent
532
+ */
533
+ function getExtentPixelCount(extent) {
534
+ const [sx, sy, sz] = getExtentSize(extent);
535
+ return sx * sy * sz;
536
+ }
537
+
538
+ //----------------------------------------------------------------------------
539
+
540
+ /**
541
+ * Reads a flattened extent from the image data and writes to the given output array.
542
+ *
543
+ * Assumes X varies the fastest and Z varies the slowest.
544
+ *
545
+ * @param {*} data
546
+ * @param {*} dataDims
547
+ * @param {Extent} extent
548
+ * @param {TypedArray} outArray
549
+ * @param {number} outOffset
550
+ * @returns
551
+ */
552
+ function readExtentIntoArray(data, dataDims, extent, outArray, outOffset) {
553
+ const [xmin, xmax, ymin, ymax, zmin, zmax] = extent;
554
+ const [dx, dy] = dataDims;
555
+ const sxy = dx * dy;
556
+ let writeOffset = outOffset;
557
+ for (let zi = zmin; zi <= zmax; zi++) {
558
+ const zOffset = zi * sxy;
559
+ for (let yi = ymin; yi <= ymax; yi++) {
560
+ const zyOffset = zOffset + yi * dx;
561
+ // explicit alternative to data.subarray,
562
+ // due to potential perf issues on v8
563
+ for (let readOffset = zyOffset + xmin, end = zyOffset + xmax; readOffset <= end; readOffset++, writeOffset++) {
564
+ outArray[writeOffset] = data[readOffset];
565
+ }
566
+ }
567
+ }
568
+ }
569
+
570
+ //----------------------------------------------------------------------------
571
+
572
+ /**
573
+ * Reads several image extents into a contiguous pixel array.
574
+ *
575
+ * @param {*} data
576
+ * @param {Extent[]} extent
577
+ * @param {TypedArrayConstructor} typedArrayConstructor optional typed array constructor
578
+ * @returns
579
+ */
580
+ function readExtents(data, extents) {
581
+ let typedArrayConstructor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
582
+ const constructor = typedArrayConstructor || data.constructor;
583
+ const numPixels = extents.reduce((count, extent) => count + getExtentPixelCount(extent), 0);
584
+ const extentPixels = new constructor(numPixels);
585
+ const dataDims = [model.width, model.height, model.depth];
586
+ let writeOffset = 0;
587
+ extents.forEach(extent => {
588
+ readExtentIntoArray(data, dataDims, extent, extentPixels, writeOffset);
589
+ writeOffset += getExtentPixelCount(extent);
590
+ });
591
+ return extentPixels;
592
+ }
593
+
594
+ //----------------------------------------------------------------------------
595
+
495
596
  /**
496
597
  * Updates the data array to match the required data type for OpenGL.
497
598
  *
@@ -501,23 +602,30 @@ function vtkOpenGLTexture(publicAPI, model) {
501
602
  * @param {string} dataType - The original data type of the input data.
502
603
  * @param {Array} data - The input data array that needs to be updated.
503
604
  * @param {boolean} [depth=false] - Indicates whether the data is a 3D array.
605
+ * @param {Array<Extent>} imageExtents only consider these image extents (default: [])
504
606
  * @returns {Array} The updated data array that matches the OpenGL data type.
505
607
  */
506
608
  publicAPI.updateArrayDataTypeForGL = function (dataType, data) {
507
609
  let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
610
+ let imageExtents = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
508
611
  const pixData = [];
509
612
  let pixCount = model.width * model.height * model.components;
510
613
  if (depth) {
511
614
  pixCount *= model.depth;
512
615
  }
616
+ const onlyUpdateExtents = !!imageExtents.length;
513
617
 
514
618
  // if the opengl data type is float
515
619
  // then the data array must be float
516
620
  if (dataType !== VtkDataTypes.FLOAT && model.openGLDataType === model.context.FLOAT) {
517
621
  for (let idx = 0; idx < data.length; idx++) {
518
622
  if (data[idx]) {
519
- const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
520
- pixData.push(new Float32Array(dataArrayToCopy));
623
+ if (onlyUpdateExtents) {
624
+ pixData.push(readExtents(data[idx], imageExtents, Float32Array));
625
+ } else {
626
+ const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
627
+ pixData.push(new Float32Array(dataArrayToCopy));
628
+ }
521
629
  } else {
522
630
  pixData.push(null);
523
631
  }
@@ -529,8 +637,12 @@ function vtkOpenGLTexture(publicAPI, model) {
529
637
  if (dataType !== VtkDataTypes.UNSIGNED_CHAR && model.openGLDataType === model.context.UNSIGNED_BYTE) {
530
638
  for (let idx = 0; idx < data.length; idx++) {
531
639
  if (data[idx]) {
532
- const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
533
- pixData.push(new Uint8Array(dataArrayToCopy));
640
+ if (onlyUpdateExtents) {
641
+ pixData.push(readExtents(data[idx], imageExtents, Uint8Array));
642
+ } else {
643
+ const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
644
+ pixData.push(new Uint8Array(dataArrayToCopy));
645
+ }
534
646
  } else {
535
647
  pixData.push(null);
536
648
  }
@@ -549,9 +661,10 @@ function vtkOpenGLTexture(publicAPI, model) {
549
661
  if (halfFloat) {
550
662
  for (let idx = 0; idx < data.length; idx++) {
551
663
  if (data[idx]) {
552
- const newArray = new Uint16Array(pixCount);
553
- const src = data[idx];
554
- for (let i = 0; i < pixCount; i++) {
664
+ const src = onlyUpdateExtents ? readExtents(data[idx], imageExtents) : data[idx];
665
+ const newArray = new Uint16Array(onlyUpdateExtents ? src.length : pixCount);
666
+ const newArrayLen = newArray.length;
667
+ for (let i = 0; i < newArrayLen; i++) {
555
668
  newArray[i] = toHalf(src[i]);
556
669
  }
557
670
  pixData.push(newArray);
@@ -564,7 +677,7 @@ function vtkOpenGLTexture(publicAPI, model) {
564
677
  // The output has to be filled
565
678
  if (pixData.length === 0) {
566
679
  for (let i = 0; i < data.length; i++) {
567
- pixData.push(data[i]);
680
+ pixData.push(onlyUpdateExtents && data[i] ? readExtents(data[i], imageExtents) : data[i]);
568
681
  }
569
682
  }
570
683
  return pixData;
@@ -659,7 +772,7 @@ function vtkOpenGLTexture(publicAPI, model) {
659
772
  }
660
773
  if (model._openGLRenderWindow.getWebgl2()) {
661
774
  const webGLInfo = model._openGLRenderWindow.getGLInformations();
662
- if (webGLInfo.RENDERER.value.match(/WebKit/gi) && navigator.platform.match(/Mac/gi) && model.oglNorm16Ext && (dataType === VtkDataTypes.UNSIGNED_SHORT || dataType === VtkDataTypes.SHORT)) {
775
+ if (webGLInfo.RENDERER.value.match(/WebKit/gi) && navigator.platform.match(/Mac/gi) && getNorm16Ext() && (dataType === VtkDataTypes.UNSIGNED_SHORT || dataType === VtkDataTypes.SHORT)) {
663
776
  // Cannot use texStorage with EXT_texture_norm16 textures on Mac M1 GPU.
664
777
  // No errors reported but the texture is unusable.
665
778
  return false;
@@ -717,7 +830,7 @@ function vtkOpenGLTexture(publicAPI, model) {
717
830
  if (flip) {
718
831
  model.context.pixelStorei(model.context.UNPACK_FLIP_Y_WEBGL, false);
719
832
  }
720
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
833
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
721
834
  publicAPI.deactivate();
722
835
  return true;
723
836
  };
@@ -795,7 +908,7 @@ function vtkOpenGLTexture(publicAPI, model) {
795
908
  h /= 2;
796
909
  }
797
910
  }
798
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
911
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * numComps * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
799
912
  // generateMipmap must not be called here because we manually upload all levels
800
913
  // if it is called, all levels will be overwritten
801
914
 
@@ -845,7 +958,7 @@ function vtkOpenGLTexture(publicAPI, model) {
845
958
  if (model.generateMipmap) {
846
959
  model.context.generateMipmap(model.target);
847
960
  }
848
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, model.oglNorm16Ext, publicAPI.useHalfFloat());
961
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataType, getNorm16Ext(), publicAPI.useHalfFloat());
849
962
  publicAPI.deactivate();
850
963
  return true;
851
964
  };
@@ -895,7 +1008,7 @@ function vtkOpenGLTexture(publicAPI, model) {
895
1008
  if (model.generateMipmap) {
896
1009
  model.context.generateMipmap(model.target);
897
1010
  }
898
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, model.oglNorm16Ext, publicAPI.useHalfFloat());
1011
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(VtkDataTypes.UNSIGNED_CHAR, getNorm16Ext(), publicAPI.useHalfFloat());
899
1012
  publicAPI.deactivate();
900
1013
  return true;
901
1014
  };
@@ -979,10 +1092,12 @@ function vtkOpenGLTexture(publicAPI, model) {
979
1092
  }
980
1093
  publicAPI.create2DFilterableFromRaw = function (width, height, numberOfComponents, dataType, values) {
981
1094
  let preferSizeOverAccuracy = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
1095
+ let ranges = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : undefined;
982
1096
  return publicAPI.create2DFilterableFromDataArray(width, height, vtkDataArray.newInstance({
983
1097
  numberOfComponents,
984
1098
  dataType,
985
- values
1099
+ values,
1100
+ ranges
986
1101
  }), preferSizeOverAccuracy);
987
1102
  };
988
1103
  publicAPI.create2DFilterableFromDataArray = function (width, height, dataArray) {
@@ -1013,7 +1128,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1013
1128
  }
1014
1129
 
1015
1130
  // Handle SHORT data type with EXT_texture_norm16 extension
1016
- if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.SHORT) {
1131
+ if (getNorm16Ext() && !useHalfFloat && dataType === VtkDataTypes.SHORT) {
1017
1132
  for (let c = 0; c < numComps; ++c) {
1018
1133
  model.volumeInfo.scale[c] = 32767.0; // Scale to [-1, 1] range
1019
1134
  }
@@ -1022,7 +1137,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1022
1137
  }
1023
1138
 
1024
1139
  // Handle UNSIGNED_SHORT data type with EXT_texture_norm16 extension
1025
- if (model.oglNorm16Ext && !useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1140
+ if (getNorm16Ext() && !useHalfFloat && dataType === VtkDataTypes.UNSIGNED_SHORT) {
1026
1141
  for (let c = 0; c < numComps; ++c) {
1027
1142
  model.volumeInfo.scale[c] = 65535.0; // Scale to [0, 1] range
1028
1143
  }
@@ -1047,7 +1162,8 @@ function vtkOpenGLTexture(publicAPI, model) {
1047
1162
  };
1048
1163
 
1049
1164
  //----------------------------------------------------------------------------
1050
- publicAPI.create3DFromRaw = (width, height, depth, numComps, dataType, data) => {
1165
+ publicAPI.create3DFromRaw = function (width, height, depth, numComps, dataType, data) {
1166
+ let updatedExtents = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : [];
1051
1167
  let dataTypeToUse = dataType;
1052
1168
  let dataToUse = data;
1053
1169
  if (!publicAPI.updateVolumeInfoForGL(dataTypeToUse, numComps) && dataToUse) {
@@ -1089,30 +1205,47 @@ function vtkOpenGLTexture(publicAPI, model) {
1089
1205
  model._openGLRenderWindow.activateTexture(publicAPI);
1090
1206
  publicAPI.createTexture();
1091
1207
  publicAPI.bind();
1208
+ const hasUpdatedExtents = updatedExtents.length > 0;
1209
+
1210
+ // It's possible for the texture parameters to change while
1211
+ // streaming, so check for such a change.
1212
+ const rebuildEntireTexture = !hasUpdatedExtents || !DeepEqual(model._prevTexParams, getTexParams());
1213
+
1092
1214
  // Create an array of texture with one texture
1093
1215
  const dataArray = [dataToUse];
1094
1216
  const is3DArray = true;
1095
- const pixData = publicAPI.updateArrayDataTypeForGL(dataTypeToUse, dataArray, is3DArray);
1217
+ const pixData = publicAPI.updateArrayDataTypeForGL(dataTypeToUse, dataArray, is3DArray, rebuildEntireTexture ? [] : updatedExtents);
1096
1218
  const scaledData = scaleTextureToHighestPowerOfTwo(pixData);
1097
1219
 
1098
1220
  // Source texture data from the PBO.
1099
1221
  // model.context.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
1100
1222
  model.context.pixelStorei(model.context.UNPACK_ALIGNMENT, 1);
1101
-
1102
- // openGLDataType
1103
-
1104
- if (useTexStorage(dataTypeToUse)) {
1105
- model.context.texStorage3D(model.target, 1, model.internalFormat, model.width, model.height, model.depth);
1106
- if (scaledData[0] != null) {
1107
- model.context.texSubImage3D(model.target, 0, 0, 0, 0, model.width, model.height, model.depth, model.format, model.openGLDataType, scaledData[0]);
1223
+ if (rebuildEntireTexture) {
1224
+ if (useTexStorage(dataTypeToUse)) {
1225
+ model.context.texStorage3D(model.target, 1, model.internalFormat, model.width, model.height, model.depth);
1226
+ if (scaledData[0] != null) {
1227
+ model.context.texSubImage3D(model.target, 0, 0, 0, 0, model.width, model.height, model.depth, model.format, model.openGLDataType, scaledData[0]);
1228
+ }
1229
+ } else {
1230
+ model.context.texImage3D(model.target, 0, model.internalFormat, model.width, model.height, model.depth, 0, model.format, model.openGLDataType, scaledData[0]);
1231
+ }
1232
+ model._prevTexParams = getTexParams();
1233
+ } else if (hasUpdatedExtents) {
1234
+ const extentPixels = scaledData[0];
1235
+ let readOffset = 0;
1236
+ for (let i = 0; i < updatedExtents.length; i++) {
1237
+ const extent = updatedExtents[i];
1238
+ const extentSize = getExtentSize(extent);
1239
+ const extentPixelCount = getExtentPixelCount(extent);
1240
+ const textureData = new extentPixels.constructor(extentPixels.buffer, readOffset, extentPixelCount);
1241
+ readOffset += textureData.byteLength;
1242
+ model.context.texSubImage3D(model.target, 0, extent[0], extent[2], extent[4], extentSize[0], extentSize[1], extentSize[2], model.format, model.openGLDataType, textureData);
1108
1243
  }
1109
- } else {
1110
- model.context.texImage3D(model.target, 0, model.internalFormat, model.width, model.height, model.depth, 0, model.format, model.openGLDataType, scaledData[0]);
1111
1244
  }
1112
1245
  if (model.generateMipmap) {
1113
1246
  model.context.generateMipmap(model.target);
1114
1247
  }
1115
- model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataTypeToUse, model.oglNorm16Ext, publicAPI.useHalfFloat());
1248
+ model.allocatedGPUMemoryInBytes = model.width * model.height * model.depth * model.components * model._openGLRenderWindow.getDefaultTextureByteSize(dataTypeToUse, getNorm16Ext(), publicAPI.useHalfFloat());
1116
1249
  publicAPI.deactivate();
1117
1250
  return true;
1118
1251
  };
@@ -1122,17 +1255,21 @@ function vtkOpenGLTexture(publicAPI, model) {
1122
1255
  // Prefer create3DFilterableFromDataArray to enable caching of min and max values
1123
1256
  publicAPI.create3DFilterableFromRaw = function (width, height, depth, numberOfComponents, dataType, values) {
1124
1257
  let preferSizeOverAccuracy = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
1258
+ let ranges = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : undefined;
1259
+ let updatedExtents = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : [];
1125
1260
  return publicAPI.create3DFilterableFromDataArray(width, height, depth, vtkDataArray.newInstance({
1126
1261
  numberOfComponents,
1127
1262
  dataType,
1128
- values
1129
- }), preferSizeOverAccuracy);
1263
+ values,
1264
+ ranges
1265
+ }), preferSizeOverAccuracy, updatedExtents);
1130
1266
  };
1131
1267
 
1132
1268
  //----------------------------------------------------------------------------
1133
1269
  // This method create a 3D texture from dimensions and a DataArray
1134
1270
  publicAPI.create3DFilterableFromDataArray = function (width, height, depth, dataArray) {
1135
1271
  let preferSizeOverAccuracy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
1272
+ let updatedExtents = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : [];
1136
1273
  const {
1137
1274
  numComps,
1138
1275
  dataType,
@@ -1167,7 +1304,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1167
1304
 
1168
1305
  // WebGL2 path, we have 3d textures etc
1169
1306
  if (model._openGLRenderWindow.getWebgl2()) {
1170
- return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
1307
+ return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data, updatedExtents);
1171
1308
  }
1172
1309
  const numPixelsIn = width * height * depth;
1173
1310
  const scaleOffsetsCopy = structuredClone(scaleOffsets);
@@ -1336,6 +1473,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1336
1473
  const DEFAULT_VALUES = {
1337
1474
  _openGLRenderWindow: null,
1338
1475
  _forceInternalFormat: false,
1476
+ _prevTexParams: null,
1339
1477
  context: null,
1340
1478
  handle: 0,
1341
1479
  sendParametersTime: null,
@@ -1034,7 +1034,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1034
1034
  if (reBuildOp) {
1035
1035
  const newOpacityTexture = vtkOpenGLTexture.newInstance();
1036
1036
  newOpacityTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1037
- const oWidth = 1024;
1037
+ let oWidth = model.renderable.getOpacityTextureWidth();
1038
+ if (oWidth <= 0) {
1039
+ oWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
1040
+ }
1038
1041
  const oSize = oWidth * 2 * numIComps;
1039
1042
  const ofTable = new Float32Array(oSize);
1040
1043
  const tmpTable = new Float32Array(oWidth);
@@ -1088,7 +1091,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1088
1091
  if (reBuildC) {
1089
1092
  const newColorTexture = vtkOpenGLTexture.newInstance();
1090
1093
  newColorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1091
- const cWidth = 1024;
1094
+ let cWidth = model.renderable.getColorTextureWidth();
1095
+ if (cWidth <= 0) {
1096
+ cWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
1097
+ }
1092
1098
  const cSize = cWidth * 2 * numIComps * 3;
1093
1099
  const cTable = new Uint8ClampedArray(cSize);
1094
1100
  const tmpTable = new Float32Array(cWidth * 3);
@@ -1125,7 +1131,9 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1125
1131
  const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
1126
1132
  const scalarsHash = getImageDataHash(imageData, scalars);
1127
1133
  const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== scalarsHash;
1128
- if (reBuildTex) {
1134
+ const updatedExtents = volumeProperty.getUpdatedExtents();
1135
+ const hasUpdatedExtents = !!updatedExtents.length;
1136
+ if (reBuildTex && !hasUpdatedExtents) {
1129
1137
  const newScalarTexture = vtkOpenGLTexture.newInstance();
1130
1138
  newScalarTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1131
1139
  // Build the textures
@@ -1139,6 +1147,13 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1139
1147
  } else {
1140
1148
  model.scalarTextures[component] = tex.oglObject;
1141
1149
  }
1150
+ if (hasUpdatedExtents) {
1151
+ // If hasUpdatedExtents, then the texture is partially updated.
1152
+ // clear the array to acknowledge the update.
1153
+ volumeProperty.setUpdatedExtents([]);
1154
+ const dims = imageData.getDimensions();
1155
+ model.scalarTextures[component].create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, false, updatedExtents);
1156
+ }
1142
1157
  replaceGraphicsResource(model._openGLRenderWindow, model._scalarTexturesCore[component], scalars);
1143
1158
  model._scalarTexturesCore[component] = scalars;
1144
1159
  });
@@ -1151,7 +1166,10 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
1151
1166
  if (reBuildL) {
1152
1167
  const newLabelOutlineThicknessTexture = vtkOpenGLTexture.newInstance();
1153
1168
  newLabelOutlineThicknessTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
1154
- const lWidth = 1024;
1169
+ let lWidth = model.renderable.getLabelOutlineTextureWidth();
1170
+ if (lWidth <= 0) {
1171
+ lWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
1172
+ }
1155
1173
  const lHeight = 1;
1156
1174
  const lSize = lWidth * lHeight;
1157
1175
  const lTable = new Uint8Array(lSize);
@@ -105,13 +105,23 @@ function vtkViewNode(publicAPI, model) {
105
105
 
106
106
  // add missing nodes/children for the passed in renderables. This should
107
107
  // be called only in between prepareNodes and removeUnusedNodes
108
- publicAPI.addMissingNodes = dataObjs => {
108
+ publicAPI.addMissingNodes = function (dataObjs) {
109
+ let enforceOrder = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
109
110
  if (!dataObjs || !dataObjs.length) {
110
111
  return;
111
112
  }
112
113
  for (let index = 0; index < dataObjs.length; ++index) {
113
114
  const dobj = dataObjs[index];
114
- publicAPI.addMissingNode(dobj);
115
+ const node = publicAPI.addMissingNode(dobj);
116
+ if (enforceOrder && node !== undefined && model.children[index] !== node) {
117
+ for (let i = index + 1; i < model.children.length; ++i) {
118
+ if (model.children[i] === node) {
119
+ model.children.splice(i, 1);
120
+ model.children.splice(index, 0, node);
121
+ break;
122
+ }
123
+ }
124
+ }
115
125
  }
116
126
  };
117
127
 
@@ -140,6 +140,15 @@ function vtkWebXRRenderWindowHelper(publicAPI, model) {
140
140
  model.renderWindow.getRenderable().getInteractor().returnFromXRAnimation();
141
141
  const gl = model.renderWindow.get3DContext();
142
142
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
143
+
144
+ // Remove controllers ray
145
+ const ren = model.renderWindow.getRenderable().getRenderers()[0];
146
+ model.xrSession.inputSources.forEach(inputSource => {
147
+ if (model.inputSourceToRay[inputSource.handedness]) {
148
+ ren.removeActor(model.inputSourceToRay[inputSource.handedness].actor);
149
+ model.inputSourceToRay[inputSource.handedness].visible = false;
150
+ }
151
+ });
143
152
  await model.xrSession.end().catch(error => {
144
153
  if (!(error instanceof DOMException)) {
145
154
  throw error;
@@ -12,6 +12,14 @@ import { vtkObject } from './../../interfaces';
12
12
  import { CaptureOn, ViewTypes } from './WidgetManager/Constants';
13
13
  import { Nullable } from './../../types';
14
14
 
15
+ export interface IDisplayScaleParams {
16
+ dispHeightFactor: number;
17
+ cameraPosition: number[];
18
+ cameraDir: number[];
19
+ isParallel: boolean;
20
+ rendererPixelDims: number[];
21
+ }
22
+
15
23
  export interface ISelectedData {
16
24
  requestCount: number;
17
25
  propID: number;
@@ -45,7 +53,10 @@ export function extractRenderingComponents(
45
53
  * (vertical) distance that matches a display distance of 30px for a coordinate
46
54
  * `coord`, you would compute `30 * getPixelWorldHeightAtCoord(coord)`.
47
55
  */
48
- export function getPixelWorldHeightAtCoord(coord: []): Number;
56
+ export function getPixelWorldHeightAtCoord(
57
+ coord: [],
58
+ displayScaleParams: IDisplayScaleParams
59
+ ): Number;
49
60
 
50
61
  export interface vtkWidgetManager extends vtkObject {
51
62
  /**