@kitware/vtk.js 33.0.0-beta.3 → 33.0.0

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 (58) hide show
  1. package/BREAKING_CHANGES.md +0 -3
  2. package/Common/Core/DataArray.d.ts +17 -0
  3. package/Common/Core/DataArray.js +36 -0
  4. package/Common/Core/ScalarsToColors/Constants.js +7 -2
  5. package/Common/Core/ScalarsToColors.js +3 -1
  6. package/Rendering/Core/AbstractImageMapper.d.ts +81 -0
  7. package/Rendering/Core/AbstractImageMapper.js +5 -2
  8. package/Rendering/Core/AbstractPicker.d.ts +13 -13
  9. package/Rendering/Core/AbstractPicker.js +1 -1
  10. package/Rendering/Core/Actor.d.ts +20 -5
  11. package/Rendering/Core/Actor.js +68 -5
  12. package/Rendering/Core/Actor2D.d.ts +22 -0
  13. package/Rendering/Core/Actor2D.js +1 -1
  14. package/Rendering/Core/CellPicker.js +4 -1
  15. package/Rendering/Core/ColorTransferFunction.js +26 -35
  16. package/Rendering/Core/ImageCPRMapper.d.ts +20 -1
  17. package/Rendering/Core/ImageCPRMapper.js +7 -5
  18. package/Rendering/Core/ImageResliceMapper.d.ts +20 -2
  19. package/Rendering/Core/ImageResliceMapper.js +7 -5
  20. package/Rendering/Core/ImageSlice.d.ts +23 -7
  21. package/Rendering/Core/ImageSlice.js +68 -9
  22. package/Rendering/Core/Mapper.js +8 -16
  23. package/Rendering/Core/Prop3D.d.ts +2 -39
  24. package/Rendering/Core/Prop3D.js +2 -81
  25. package/Rendering/Core/ScalarBarActor.js +4 -2
  26. package/Rendering/Core/Viewport.js +13 -3
  27. package/Rendering/Core/Volume.d.ts +20 -5
  28. package/Rendering/Core/Volume.js +70 -2
  29. package/Rendering/Core/VolumeMapper/Constants.d.ts +7 -0
  30. package/Rendering/Core/VolumeMapper/Constants.js +8 -2
  31. package/Rendering/Core/VolumeMapper.d.ts +243 -16
  32. package/Rendering/Core/VolumeMapper.js +60 -20
  33. package/Rendering/Core/VolumeProperty/Constants.d.ts +3 -12
  34. package/Rendering/Core/VolumeProperty/Constants.js +4 -11
  35. package/Rendering/Core/VolumeProperty.d.ts +4 -120
  36. package/Rendering/Core/VolumeProperty.js +4 -49
  37. package/Rendering/Misc/SynchronizableRenderWindow/BehaviorManager/CameraSynchronizer.js +2 -2
  38. package/Rendering/OpenGL/ImageCPRMapper.js +36 -29
  39. package/Rendering/OpenGL/ImageMapper.js +55 -31
  40. package/Rendering/OpenGL/ImageResliceMapper.js +191 -263
  41. package/Rendering/OpenGL/PolyDataMapper.js +8 -1
  42. package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.d.ts +3 -3
  43. package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.js +5 -8
  44. package/Rendering/OpenGL/Renderer.js +1 -1
  45. package/Rendering/OpenGL/Texture.d.ts +29 -8
  46. package/Rendering/OpenGL/Texture.js +154 -23
  47. package/Rendering/OpenGL/VolumeMapper.js +792 -712
  48. package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
  49. package/Rendering/SceneGraph/ViewNode.js +12 -2
  50. package/Rendering/WebGPU/VolumePassFSQ.js +2 -2
  51. package/Rendering/WebXR/RenderWindowHelper.js +9 -0
  52. package/Widgets/Core/WidgetManager.d.ts +12 -1
  53. package/Widgets/Representations/WidgetRepresentation.d.ts +1 -7
  54. package/Widgets/Widgets3D/ResliceCursorWidget.d.ts +1 -8
  55. package/index.d.ts +0 -1
  56. package/macros2.js +1 -1
  57. package/package.json +11 -11
  58. package/Interaction/Manipulators/KeyboardCameraManipulator.d.ts +0 -113
@@ -2,7 +2,7 @@ import { mat3, mat4, vec3 } from 'gl-matrix';
2
2
  import { n as newInstance$1, e as setGet, o as obj, c as macro } from '../../macros2.js';
3
3
  import vtkHelper from './Helper.js';
4
4
  import vtkMapper from '../Core/Mapper.js';
5
- import { l as normalize } from '../../Common/Core/Math/index.js';
5
+ import { l as normalize, u as uninitializeBounds } from '../../Common/Core/Math/index.js';
6
6
  import vtkOpenGLTexture from './Texture.js';
7
7
  import vtkProp from '../Core/Prop.js';
8
8
  import vtkProperty from '../Core/Property.js';
@@ -941,6 +941,13 @@ function vtkOpenGLPolyDataMapper(publicAPI, model) {
941
941
  publicAPI.renderPieceDraw(ren, actor);
942
942
  publicAPI.renderPieceFinish(ren, actor);
943
943
  };
944
+ publicAPI.computeBounds = (ren, actor) => {
945
+ if (!publicAPI.getInput()) {
946
+ uninitializeBounds(model.bounds);
947
+ return;
948
+ }
949
+ model.bounds = publicAPI.getInput().getBounds();
950
+ };
944
951
  publicAPI.updateBufferObjects = (ren, actor) => {
945
952
  // Rebuild buffers if needed
946
953
  if (publicAPI.getNeedToRebuildBufferObjects(ren, actor)) {
@@ -9,8 +9,8 @@ import { vtkObject } from '../../../interfaces';
9
9
  * @param useIndependentComponents A boolean taken from the image or volume property, using getIndependentComponents()
10
10
  * @param numberOfComponents Taken from the data array, using getNumberOfComponents()
11
11
  */
12
- export function getTransferFunctionsHash(
13
- transferFunctions: (vtkObject | null | undefined)[],
12
+ export function getTransferFunctionHash(
13
+ transferFunction: vtkObject | undefined,
14
14
  useIndependentComponents: boolean,
15
15
  numberOfComponents: number
16
16
  ): string;
@@ -27,7 +27,7 @@ export function getImageDataHash(
27
27
  ): string;
28
28
 
29
29
  declare const defaultExport: {
30
- getTransferFunctionsHash: typeof getTransferFunctionsHash;
30
+ getTransferFunctionHash: typeof getTransferFunctionHash;
31
31
  getImageDataHash: typeof getImageDataHash;
32
32
  };
33
33
 
@@ -1,17 +1,14 @@
1
1
  // See typescript header for documentation
2
2
 
3
- function getTransferFunctionsHash(transferFunctions, useIndependentComponents, numberOfComponents) {
4
- return transferFunctions.length > 0 ? `${transferFunctions.map(tf => tf?.getMTime() ?? 'x').join('/')}-${useIndependentComponents}-${numberOfComponents}` : '0';
3
+ function getTransferFunctionHash(transferFunction, useIndependentComponents, numberOfComponents) {
4
+ return transferFunction ? `${transferFunction.getMTime()}-${useIndependentComponents}-${numberOfComponents}` : '0';
5
5
  }
6
6
  function getImageDataHash(image, scalars) {
7
- // Don't use the image data, as the scalars will define the texture
8
- // If using the image data in the hash, it will cause issues when two image data
9
- // using the same scalars are in the same mapper (for example the VolumeMapper)
10
- return `${scalars.getMTime()}`;
7
+ return `${image.getMTime()}A${scalars.getMTime()}`;
11
8
  }
12
9
  var resourceSharingHelper = {
13
- getTransferFunctionsHash,
10
+ getTransferFunctionHash,
14
11
  getImageDataHash
15
12
  };
16
13
 
17
- export { resourceSharingHelper as default, getImageDataHash, getTransferFunctionsHash };
14
+ export { resourceSharingHelper as default, getImageDataHash, getTransferFunctionHash };
@@ -24,7 +24,7 @@ function vtkOpenGLRenderer(publicAPI, model) {
24
24
  publicAPI.updateLights();
25
25
  publicAPI.prepareNodes();
26
26
  publicAPI.addMissingNode(model.renderable.getActiveCamera());
27
- publicAPI.addMissingNodes(model.renderable.getViewPropsWithNestedProps());
27
+ publicAPI.addMissingNodes(model.renderable.getViewPropsWithNestedProps(), true);
28
28
  publicAPI.removeUnusedNodes();
29
29
  }
30
30
  };
@@ -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';
@@ -30,6 +31,16 @@ const {
30
31
  function vtkOpenGLTexture(publicAPI, model) {
31
32
  // Set our className
32
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
+
33
44
  // Renders myself
34
45
  publicAPI.render = function () {
35
46
  let renWin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
@@ -148,6 +159,7 @@ function vtkOpenGLTexture(publicAPI, model) {
148
159
  if (model.context && model.handle) {
149
160
  model.context.deleteTexture(model.handle);
150
161
  }
162
+ model._prevTexParams = null;
151
163
  model.handle = 0;
152
164
  model.numberOfDimensions = 0;
153
165
  model.target = 0;
@@ -209,6 +221,7 @@ function vtkOpenGLTexture(publicAPI, model) {
209
221
  rwin.activateTexture(publicAPI);
210
222
  rwin.deactivateTexture(publicAPI);
211
223
  model.context.deleteTexture(model.handle);
224
+ model._prevTexParams = null;
212
225
  model.handle = 0;
213
226
  model.numberOfDimensions = 0;
214
227
  model.target = 0;
@@ -353,6 +366,7 @@ function vtkOpenGLTexture(publicAPI, model) {
353
366
 
354
367
  //----------------------------------------------------------------------------
355
368
  publicAPI.resetFormatAndType = () => {
369
+ model._prevTexParams = null;
356
370
  model.format = 0;
357
371
  model.internalFormat = 0;
358
372
  model._forceInternalFormat = false;
@@ -499,6 +513,86 @@ function vtkOpenGLTexture(publicAPI, model) {
499
513
  }
500
514
  };
501
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
+
502
596
  /**
503
597
  * Updates the data array to match the required data type for OpenGL.
504
598
  *
@@ -508,23 +602,30 @@ function vtkOpenGLTexture(publicAPI, model) {
508
602
  * @param {string} dataType - The original data type of the input data.
509
603
  * @param {Array} data - The input data array that needs to be updated.
510
604
  * @param {boolean} [depth=false] - Indicates whether the data is a 3D array.
605
+ * @param {Array<Extent>} imageExtents only consider these image extents (default: [])
511
606
  * @returns {Array} The updated data array that matches the OpenGL data type.
512
607
  */
513
608
  publicAPI.updateArrayDataTypeForGL = function (dataType, data) {
514
609
  let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
610
+ let imageExtents = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
515
611
  const pixData = [];
516
612
  let pixCount = model.width * model.height * model.components;
517
613
  if (depth) {
518
614
  pixCount *= model.depth;
519
615
  }
616
+ const onlyUpdateExtents = !!imageExtents.length;
520
617
 
521
618
  // if the opengl data type is float
522
619
  // then the data array must be float
523
620
  if (dataType !== VtkDataTypes.FLOAT && model.openGLDataType === model.context.FLOAT) {
524
621
  for (let idx = 0; idx < data.length; idx++) {
525
622
  if (data[idx]) {
526
- const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
527
- 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
+ }
528
629
  } else {
529
630
  pixData.push(null);
530
631
  }
@@ -536,8 +637,12 @@ function vtkOpenGLTexture(publicAPI, model) {
536
637
  if (dataType !== VtkDataTypes.UNSIGNED_CHAR && model.openGLDataType === model.context.UNSIGNED_BYTE) {
537
638
  for (let idx = 0; idx < data.length; idx++) {
538
639
  if (data[idx]) {
539
- const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
540
- 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
+ }
541
646
  } else {
542
647
  pixData.push(null);
543
648
  }
@@ -556,9 +661,10 @@ function vtkOpenGLTexture(publicAPI, model) {
556
661
  if (halfFloat) {
557
662
  for (let idx = 0; idx < data.length; idx++) {
558
663
  if (data[idx]) {
559
- const newArray = new Uint16Array(pixCount);
560
- const src = data[idx];
561
- 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++) {
562
668
  newArray[i] = toHalf(src[i]);
563
669
  }
564
670
  pixData.push(newArray);
@@ -571,7 +677,7 @@ function vtkOpenGLTexture(publicAPI, model) {
571
677
  // The output has to be filled
572
678
  if (pixData.length === 0) {
573
679
  for (let i = 0; i < data.length; i++) {
574
- pixData.push(data[i]);
680
+ pixData.push(onlyUpdateExtents && data[i] ? readExtents(data[i], imageExtents) : data[i]);
575
681
  }
576
682
  }
577
683
  return pixData;
@@ -986,10 +1092,12 @@ function vtkOpenGLTexture(publicAPI, model) {
986
1092
  }
987
1093
  publicAPI.create2DFilterableFromRaw = function (width, height, numberOfComponents, dataType, values) {
988
1094
  let preferSizeOverAccuracy = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
1095
+ let ranges = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : undefined;
989
1096
  return publicAPI.create2DFilterableFromDataArray(width, height, vtkDataArray.newInstance({
990
1097
  numberOfComponents,
991
1098
  dataType,
992
- values
1099
+ values,
1100
+ ranges
993
1101
  }), preferSizeOverAccuracy);
994
1102
  };
995
1103
  publicAPI.create2DFilterableFromDataArray = function (width, height, dataArray) {
@@ -1054,7 +1162,8 @@ function vtkOpenGLTexture(publicAPI, model) {
1054
1162
  };
1055
1163
 
1056
1164
  //----------------------------------------------------------------------------
1057
- 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] : [];
1058
1167
  let dataTypeToUse = dataType;
1059
1168
  let dataToUse = data;
1060
1169
  if (!publicAPI.updateVolumeInfoForGL(dataTypeToUse, numComps) && dataToUse) {
@@ -1096,25 +1205,42 @@ function vtkOpenGLTexture(publicAPI, model) {
1096
1205
  model._openGLRenderWindow.activateTexture(publicAPI);
1097
1206
  publicAPI.createTexture();
1098
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
+
1099
1214
  // Create an array of texture with one texture
1100
1215
  const dataArray = [dataToUse];
1101
1216
  const is3DArray = true;
1102
- const pixData = publicAPI.updateArrayDataTypeForGL(dataTypeToUse, dataArray, is3DArray);
1217
+ const pixData = publicAPI.updateArrayDataTypeForGL(dataTypeToUse, dataArray, is3DArray, rebuildEntireTexture ? [] : updatedExtents);
1103
1218
  const scaledData = scaleTextureToHighestPowerOfTwo(pixData);
1104
1219
 
1105
1220
  // Source texture data from the PBO.
1106
1221
  // model.context.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
1107
1222
  model.context.pixelStorei(model.context.UNPACK_ALIGNMENT, 1);
1108
-
1109
- // openGLDataType
1110
-
1111
- if (useTexStorage(dataTypeToUse)) {
1112
- model.context.texStorage3D(model.target, 1, model.internalFormat, model.width, model.height, model.depth);
1113
- if (scaledData[0] != null) {
1114
- 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);
1115
1243
  }
1116
- } else {
1117
- model.context.texImage3D(model.target, 0, model.internalFormat, model.width, model.height, model.depth, 0, model.format, model.openGLDataType, scaledData[0]);
1118
1244
  }
1119
1245
  if (model.generateMipmap) {
1120
1246
  model.context.generateMipmap(model.target);
@@ -1129,17 +1255,21 @@ function vtkOpenGLTexture(publicAPI, model) {
1129
1255
  // Prefer create3DFilterableFromDataArray to enable caching of min and max values
1130
1256
  publicAPI.create3DFilterableFromRaw = function (width, height, depth, numberOfComponents, dataType, values) {
1131
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] : [];
1132
1260
  return publicAPI.create3DFilterableFromDataArray(width, height, depth, vtkDataArray.newInstance({
1133
1261
  numberOfComponents,
1134
1262
  dataType,
1135
- values
1136
- }), preferSizeOverAccuracy);
1263
+ values,
1264
+ ranges
1265
+ }), preferSizeOverAccuracy, updatedExtents);
1137
1266
  };
1138
1267
 
1139
1268
  //----------------------------------------------------------------------------
1140
1269
  // This method create a 3D texture from dimensions and a DataArray
1141
1270
  publicAPI.create3DFilterableFromDataArray = function (width, height, depth, dataArray) {
1142
1271
  let preferSizeOverAccuracy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
1272
+ let updatedExtents = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : [];
1143
1273
  const {
1144
1274
  numComps,
1145
1275
  dataType,
@@ -1174,7 +1304,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1174
1304
 
1175
1305
  // WebGL2 path, we have 3d textures etc
1176
1306
  if (model._openGLRenderWindow.getWebgl2()) {
1177
- return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
1307
+ return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data, updatedExtents);
1178
1308
  }
1179
1309
  const numPixelsIn = width * height * depth;
1180
1310
  const scaleOffsetsCopy = structuredClone(scaleOffsets);
@@ -1343,6 +1473,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1343
1473
  const DEFAULT_VALUES = {
1344
1474
  _openGLRenderWindow: null,
1345
1475
  _forceInternalFormat: false,
1476
+ _prevTexParams: null,
1346
1477
  context: null,
1347
1478
  handle: 0,
1348
1479
  sendParametersTime: null,