@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
@@ -13,7 +13,6 @@ export interface IVolumePropertyInitialValues {
13
13
  specularPower?: number;
14
14
  useLabelOutline?: boolean;
15
15
  labelOutlineThickness?: number | number[];
16
- colorMixPreset?: ColorMixPreset;
17
16
  }
18
17
 
19
18
  export interface vtkVolumeProperty extends vtkObject {
@@ -72,7 +71,7 @@ export interface vtkVolumeProperty extends vtkObject {
72
71
  /**
73
72
  *
74
73
  */
75
- getColorMixPreset(): ColorMixPreset;
74
+ getColorMixPreset(): Nullable<ColorMixPreset>;
76
75
 
77
76
  /**
78
77
  *
@@ -195,7 +194,7 @@ export interface vtkVolumeProperty extends vtkObject {
195
194
 
196
195
  /**
197
196
  * Set the color mix code to a preset value
198
- * Defaults to ColorMixPreset.DEFAULT
197
+ * Set to null to use no preset
199
198
  * See the test `testColorMix` for an example on how to use this preset.
200
199
  *
201
200
  * If set to `CUSTOM`, a tag `//VTK::CustomColorMix` is made available to the
@@ -203,9 +202,9 @@ export interface vtkVolumeProperty extends vtkObject {
203
202
  * will be used to mix the colors from each component.
204
203
  * Each component is available as a rgba vec4: `comp0`, `comp1`...
205
204
  * There are other useful functions or variable available. To find them,
206
- * see `//VTK::CustomColorMix` tag in `vtkVolumeFS.glsl`.
205
+ * see `//VTK::CustomComponentsColorMix::Impl` tag in `vtkVolumeFS.glsl`.
207
206
  */
208
- setColorMixPreset(preset: ColorMixPreset): boolean;
207
+ setColorMixPreset(preset: Nullable<ColorMixPreset>): boolean;
209
208
 
210
209
  /**
211
210
  * Does the data have independent components, or do some define color only?
@@ -371,121 +370,6 @@ export interface vtkVolumeProperty extends vtkObject {
371
370
  * Get the interpolation type for sampling a volume as a string.
372
371
  */
373
372
  getInterpolationTypeAsString(): string;
374
-
375
- /**
376
- *
377
- */
378
- getAverageIPScalarRange(): Range;
379
-
380
- /**
381
- *
382
- */
383
- getAverageIPScalarRangeByReference(): Range;
384
-
385
- /**
386
- * Get the blending coefficient that interpolates between surface and volume rendering
387
- * @default 0.0
388
- */
389
- getVolumetricScatteringBlending(): number;
390
-
391
- /**
392
- * Get the global illumination reach of volume shadow
393
- * @default 0.0
394
- */
395
- getGlobalIlluminationReach(): number;
396
-
397
- /**
398
- * Get anisotropy of volume shadow scatter
399
- * @default 0.0
400
- */
401
- getAnisotropy(): number;
402
-
403
- /**
404
- * Get local ambient occlusion flag
405
- * @default false
406
- */
407
- getLocalAmbientOcclusion(): boolean;
408
-
409
- /**
410
- * Get kernel size for local ambient occlusion
411
- * @default 15
412
- */
413
- getLAOKernelSize(): number;
414
-
415
- /**
416
- * Get kernel radius for local ambient occlusion
417
- * @default 7
418
- */
419
- getLAOKernelRadius(): number;
420
-
421
- /**
422
- *
423
- * @param x
424
- * @param y
425
- */
426
- setAverageIPScalarRange(x: number, y: number): boolean;
427
-
428
- /**
429
- *
430
- * @param {Range} averageIPScalarRange
431
- */
432
- setAverageIPScalarRangeFrom(averageIPScalarRange: Range): boolean;
433
-
434
- /**
435
- * Set the normal computation to be dependent on the transfer function.
436
- * By default, the mapper relies on the scalar gradient for computing normals at sample locations
437
- * for lighting calculations. This is an approximation and can lead to inaccurate results.
438
- * When enabled, this property makes the mapper compute normals based on the accumulated opacity
439
- * at sample locations. This can generate a more accurate representation of edge structures in the
440
- * data but adds an overhead and drops frame rate.
441
- * @param computeNormalFromOpacity
442
- */
443
- setComputeNormalFromOpacity(computeNormalFromOpacity: boolean): boolean;
444
-
445
- /**
446
- * Set the blending coefficient that determines the interpolation between surface and volume rendering.
447
- * Default value of 0.0 means shadow effect is computed with phong model.
448
- * Value of 1.0 means shadow is created by volume occlusion.
449
- * @param volumeScatterBlendCoef
450
- */
451
- setVolumetricScatteringBlending(volumeScatterBlendCoef: number): void;
452
-
453
- /**
454
- * Set the global illumination reach of volume shadow. This function is only effective when volumeScatterBlendCoef is greater than 0.
455
- * Default value of 0.0 means only the neighboring voxel is considered when creating global shadow.
456
- * Value of 1.0 means the shadow ray traverses through the entire volume.
457
- * @param globalIlluminationReach
458
- */
459
- setGlobalIlluminationReach(globalIlluminationReach: number): void;
460
-
461
- /**
462
- * Set anisotropy of volume shadow scatter. This function is only effective when volumeScatterBlendCoef is greater than 0.
463
- * Default value of 0.0 means light scatters uniformly in all directions.
464
- * Value of -1.0 means light scatters backward, value of 1.0 means light scatters forward.
465
- * @param anisotropy
466
- */
467
- setAnisotropy(anisotropy: number): void;
468
-
469
- /**
470
- * Set whether to turn on local ambient occlusion (LAO). LAO is only effective if shading is on and volumeScatterBlendCoef is set to 0.
471
- * LAO effect is added to ambient lighting, so the ambient component of the actor needs to be great than 0.
472
- * @param localAmbientOcclusion
473
- */
474
- setLocalAmbientOcclusion(localAmbientOcclusion: boolean): void;
475
-
476
- /**
477
- * Set kernel size for local ambient occlusion. It specifies the number of rays that are randomly sampled in the hemisphere.
478
- * Value is clipped between 1 and 32.
479
- * @param LAOKernelSize
480
- */
481
- setLAOKernelSize(LAOKernelSize: number): void;
482
-
483
- /**
484
- * Set kernel radius for local ambient occlusion. It specifies the number of samples that are considered on each random ray.
485
- * Value must be greater than or equal to 1.
486
- * @param LAOKernelRadius
487
- */
488
- setLAOKernelRadius(LAOKernelRadius: number): void;
489
373
  }
490
374
 
491
375
  /**
@@ -1,14 +1,11 @@
1
1
  import { m as macro } from '../../macros2.js';
2
- import { E as clampValue, K as floor } from '../../Common/Core/Math/index.js';
3
2
  import vtkColorTransferFunction from './ColorTransferFunction.js';
4
3
  import vtkPiecewiseFunction from '../../Common/DataModel/PiecewiseFunction.js';
5
4
  import Constants from './VolumeProperty/Constants.js';
6
5
 
7
6
  const {
8
7
  InterpolationType,
9
- OpacityMode,
10
- FilterMode,
11
- ColorMixPreset
8
+ OpacityMode
12
9
  } = Constants;
13
10
  const {
14
11
  vtkErrorMacro
@@ -22,9 +19,6 @@ const VTK_MAX_VRCOMP = 4;
22
19
  function vtkVolumeProperty(publicAPI, model) {
23
20
  // Set our className
24
21
  model.classHierarchy.push('vtkVolumeProperty');
25
- const superClass = {
26
- ...publicAPI
27
- };
28
22
  publicAPI.getMTime = () => {
29
23
  let mTime = model.mtime;
30
24
  let time;
@@ -203,25 +197,6 @@ function vtkVolumeProperty(publicAPI, model) {
203
197
  const cap = macro.capitalize(val);
204
198
  publicAPI[`get${cap}`] = index => model.componentData[index][`${val}`];
205
199
  });
206
- publicAPI.setAverageIPScalarRange = (min, max) => {
207
- console.warn('setAverageIPScalarRange is deprecated use setIpScalarRange');
208
- publicAPI.setIpScalarRange(min, max);
209
- };
210
- publicAPI.getFilterModeAsString = () => macro.enumToString(FilterMode, model.filterMode);
211
- publicAPI.setFilterModeToOff = () => {
212
- publicAPI.setFilterMode(FilterMode.OFF);
213
- };
214
- publicAPI.setFilterModeToNormalized = () => {
215
- publicAPI.setFilterMode(FilterMode.NORMALIZED);
216
- };
217
- publicAPI.setFilterModeToRaw = () => {
218
- publicAPI.setFilterMode(FilterMode.RAW);
219
- };
220
- publicAPI.setGlobalIlluminationReach = gl => superClass.setGlobalIlluminationReach(clampValue(gl, 0.0, 1.0));
221
- publicAPI.setVolumetricScatteringBlending = vsb => superClass.setVolumetricScatteringBlending(clampValue(vsb, 0.0, 1.0));
222
- publicAPI.setAnisotropy = at => superClass.setAnisotropy(clampValue(at, -0.99, 0.99));
223
- publicAPI.setLAOKernelSize = ks => superClass.setLAOKernelSize(floor(clampValue(ks, 1, 32)));
224
- publicAPI.setLAOKernelRadius = kr => superClass.setLAOKernelRadius(kr >= 1 ? kr : 1);
225
200
  }
226
201
 
227
202
  // ----------------------------------------------------------------------------
@@ -229,7 +204,7 @@ function vtkVolumeProperty(publicAPI, model) {
229
204
  // ----------------------------------------------------------------------------
230
205
 
231
206
  const DEFAULT_VALUES = {
232
- colorMixPreset: ColorMixPreset.DEFAULT,
207
+ colorMixPreset: null,
233
208
  independentComponents: true,
234
209
  interpolationType: InterpolationType.FAST_LINEAR,
235
210
  shade: false,
@@ -239,22 +214,7 @@ const DEFAULT_VALUES = {
239
214
  specularPower: 10.0,
240
215
  useLabelOutline: false,
241
216
  labelOutlineThickness: [1],
242
- labelOutlineOpacity: 1.0,
243
- // Properties moved from volume mapper
244
- ipScalarRange: [-1000000.0, 1000000.0],
245
- filterMode: FilterMode.OFF,
246
- // ignored by WebGL so no behavior change
247
- preferSizeOverAccuracy: false,
248
- // Whether to use halfFloat representation of float, when it is inaccurate
249
- computeNormalFromOpacity: false,
250
- // volume shadow parameters
251
- volumetricScatteringBlending: 0.0,
252
- globalIlluminationReach: 0.0,
253
- anisotropy: 0.0,
254
- // local ambient occlusion
255
- localAmbientOcclusion: false,
256
- LAOKernelSize: 15,
257
- LAOKernelRadius: 7
217
+ labelOutlineOpacity: 1.0
258
218
  };
259
219
 
260
220
  // ----------------------------------------------------------------------------
@@ -285,12 +245,7 @@ function extend(publicAPI, model) {
285
245
  });
286
246
  }
287
247
  }
288
- macro.setGet(publicAPI, model, ['colorMixPreset', 'independentComponents', 'interpolationType', 'shade', 'ambient', 'diffuse', 'specular', 'specularPower', 'useLabelOutline', 'labelOutlineOpacity',
289
- // Properties moved from volume mapper
290
- 'filterMode', 'preferSizeOverAccuracy', 'computeNormalFromOpacity', 'volumetricScatteringBlending', 'globalIlluminationReach', 'anisotropy', 'localAmbientOcclusion', 'LAOKernelSize', 'LAOKernelRadius']);
291
-
292
- // Property moved from volume mapper
293
- macro.setGetArray(publicAPI, model, ['ipScalarRange'], 2);
248
+ macro.setGet(publicAPI, model, ['colorMixPreset', 'independentComponents', 'interpolationType', 'shade', 'ambient', 'diffuse', 'specular', 'specularPower', 'useLabelOutline', 'labelOutlineOpacity']);
294
249
  macro.setGetArray(publicAPI, model, ['labelOutlineThickness']);
295
250
 
296
251
  // Object methods
@@ -33,8 +33,8 @@ function vtkCameraSynchronizer(publicAPI, model) {
33
33
  }
34
34
 
35
35
  // Update listeners automatically
36
- model._srcRendererChanged = updateListeners;
37
- model._dstRendererChanged = updateListeners;
36
+ model._onSrcRendererChanged = updateListeners;
37
+ model._onDstRendererChanged = updateListeners;
38
38
  function updatePreviousValues(position, focalPoint, viewUp) {
39
39
  if (cameraState[0] !== position[0] || cameraState[1] !== position[1] || cameraState[2] !== position[2] || cameraState[3] !== focalPoint[0] || cameraState[4] !== focalPoint[1] || cameraState[5] !== focalPoint[2] || cameraState[6] !== viewUp[0] || cameraState[7] !== viewUp[1] || cameraState[8] !== viewUp[2]) {
40
40
  cameraState[0] = position[0];
@@ -11,7 +11,7 @@ import vtkOpenGLTexture from './Texture.js';
11
11
  import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
12
12
  import vtkShaderProgram from './ShaderProgram.js';
13
13
  import vtkViewNode from '../SceneGraph/ViewNode.js';
14
- import { getImageDataHash, getTransferFunctionsHash } from './RenderWindow/resourceSharingHelper.js';
14
+ import { getImageDataHash, getTransferFunctionHash } from './RenderWindow/resourceSharingHelper.js';
15
15
  import { v as vtkPolyDataVS } from './glsl/vtkPolyDataVS.glsl.js';
16
16
  import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js';
17
17
  import { registerOverride } from './ViewNodeFactory.js';
@@ -156,6 +156,8 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
156
156
  const cachedScalarsEntry = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
157
157
  const volumeTextureHash = getImageDataHash(image, scalars);
158
158
  const reBuildTex = !cachedScalarsEntry?.oglObject?.getHandle() || cachedScalarsEntry?.hash !== volumeTextureHash;
159
+ const updatedExtents = model.renderable.getUpdatedExtents();
160
+ const hasUpdatedExtents = !!updatedExtents.length;
159
161
  if (reBuildTex) {
160
162
  model.volumeTexture = vtkOpenGLTexture.newInstance();
161
163
  model.volumeTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
@@ -174,6 +176,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
174
176
  } else {
175
177
  model.volumeTexture = cachedScalarsEntry.oglObject;
176
178
  }
179
+ if (hasUpdatedExtents) {
180
+ // If hasUpdatedExtents, then the texture is partially updated.
181
+ // clear the array to acknowledge the update.
182
+ model.renderable.setUpdatedExtents([]);
183
+ const dims = image.getDimensions();
184
+ model.volumeTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, false, updatedExtents);
185
+ }
177
186
 
178
187
  // Rebuild the color texture if needed
179
188
  const numComp = scalars.getNumberOfComponents();
@@ -181,21 +190,20 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
181
190
  const iComps = ppty.getIndependentComponents();
182
191
  const numIComps = iComps ? numComp : 1;
183
192
  const textureHeight = iComps ? 2 * numIComps : 1;
184
- const colorTransferFunctions = [];
185
- for (let component = 0; component < numIComps; ++component) {
186
- colorTransferFunctions.push(ppty.getRGBTransferFunction(component));
187
- }
188
- const colorTextureHash = getTransferFunctionsHash(colorTransferFunctions, iComps, numIComps);
189
- const firstColorTransferFunc = ppty.getRGBTransferFunction();
190
- const cachedColorEntry = model._openGLRenderWindow.getGraphicsResourceForObject(firstColorTransferFunc);
193
+ const colorTransferFunc = ppty.getRGBTransferFunction();
194
+ const colorTextureHash = getTransferFunctionHash(colorTransferFunc, iComps, numIComps);
195
+ const cachedColorEntry = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
191
196
  const reBuildColorTexture = !cachedColorEntry?.oglObject?.getHandle() || cachedColorEntry?.hash !== colorTextureHash;
192
197
  if (reBuildColorTexture) {
193
- const cWidth = 1024;
198
+ let cWidth = model.renderable.getColorTextureWidth();
199
+ if (cWidth <= 0) {
200
+ cWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
201
+ }
194
202
  const cSize = cWidth * textureHeight * 3;
195
203
  const cTable = new Uint8ClampedArray(cSize);
196
204
  model.colorTexture = vtkOpenGLTexture.newInstance();
197
205
  model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
198
- if (firstColorTransferFunc) {
206
+ if (colorTransferFunc) {
199
207
  const tmpTable = new Float32Array(cWidth * 3);
200
208
  for (let c = 0; c < numIComps; c++) {
201
209
  const cfun = ppty.getRGBTransferFunction(c);
@@ -223,13 +231,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
223
231
  model.colorTexture.resetFormatAndType();
224
232
  model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
225
233
  }
226
- if (firstColorTransferFunc) {
227
- model._openGLRenderWindow.setGraphicsResourceForObject(firstColorTransferFunc, model.colorTexture, colorTextureHash);
228
- if (firstColorTransferFunc !== model._colorTransferFunc) {
229
- model._openGLRenderWindow.registerGraphicsResourceUser(firstColorTransferFunc, publicAPI);
234
+ if (colorTransferFunc) {
235
+ model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, colorTextureHash);
236
+ if (colorTransferFunc !== model._colorTransferFunc) {
237
+ model._openGLRenderWindow.registerGraphicsResourceUser(colorTransferFunc, publicAPI);
230
238
  model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
231
239
  }
232
- model._colorTransferFunc = firstColorTransferFunc;
240
+ model._colorTransferFunc = colorTransferFunc;
233
241
  }
234
242
  } else {
235
243
  model.colorTexture = cachedColorEntry.oglObject;
@@ -238,21 +246,20 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
238
246
  // Build piecewise function buffer. This buffer is used either
239
247
  // for component weighting or opacity, depending on whether we're
240
248
  // rendering components independently or not.
241
- const opacityFunctions = [];
242
- for (let component = 0; component < numIComps; ++component) {
243
- opacityFunctions.push(ppty.getPiecewiseFunction(component));
244
- }
245
- const pwfTextureHash = getTransferFunctionsHash(opacityFunctions, iComps, numIComps);
246
- const firstPwFunc = ppty.getPiecewiseFunction();
247
- const cachedPwfEntry = model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
249
+ const pwFunc = ppty.getPiecewiseFunction();
250
+ const pwfTextureHash = getTransferFunctionHash(pwFunc, iComps, numIComps);
251
+ const cachedPwfEntry = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
248
252
  const reBuildPwf = !cachedPwfEntry?.oglObject?.getHandle() || cachedPwfEntry?.hash !== pwfTextureHash;
249
253
  if (reBuildPwf) {
250
- const pwfWidth = 1024;
254
+ let pwfWidth = model.renderable.getOpacityTextureWidth();
255
+ if (pwfWidth <= 0) {
256
+ pwfWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
257
+ }
251
258
  const pwfSize = pwfWidth * textureHeight;
252
259
  const pwfTable = new Uint8ClampedArray(pwfSize);
253
260
  model.pwfTexture = vtkOpenGLTexture.newInstance();
254
261
  model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
255
- if (firstPwFunc) {
262
+ if (pwFunc) {
256
263
  const pwfFloatTable = new Float32Array(pwfSize);
257
264
  const tmpTable = new Float32Array(pwfWidth);
258
265
  for (let c = 0; c < numIComps; ++c) {
@@ -284,13 +291,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
284
291
  model.pwfTexture.resetFormatAndType();
285
292
  model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
286
293
  }
287
- if (firstPwFunc) {
288
- model._openGLRenderWindow.setGraphicsResourceForObject(firstPwFunc, model.pwfTexture, pwfTextureHash);
289
- if (firstPwFunc !== model._pwFunc) {
290
- model._openGLRenderWindow.registerGraphicsResourceUser(firstPwFunc, publicAPI);
294
+ if (pwFunc) {
295
+ model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, pwfTextureHash);
296
+ if (pwFunc !== model._pwFunc) {
297
+ model._openGLRenderWindow.registerGraphicsResourceUser(pwFunc, publicAPI);
291
298
  model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
292
299
  }
293
- model._pwFunc = firstPwFunc;
300
+ model._pwFunc = pwFunc;
294
301
  }
295
302
  } else {
296
303
  model.pwfTexture = cachedPwfEntry.oglObject;
@@ -4,13 +4,14 @@ import { n as newInstance$1, e as setGet, o as obj, r as vtkErrorMacro$1, h as c
4
4
  import vtkDataArray from '../../Common/Core/DataArray.js';
5
5
  import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js';
6
6
  import vtkHelper from './Helper.js';
7
+ import { u as uninitializeBounds } from '../../Common/Core/Math/index.js';
7
8
  import vtkOpenGLTexture from './Texture.js';
8
9
  import vtkShaderProgram from './ShaderProgram.js';
9
10
  import vtkViewNode from '../SceneGraph/ViewNode.js';
10
11
  import { Representation } from '../Core/Property/Constants.js';
11
12
  import { Filter, Wrap } from './Texture/Constants.js';
12
13
  import { InterpolationType } from '../Core/ImageProperty/Constants.js';
13
- import { getTransferFunctionsHash } from './RenderWindow/resourceSharingHelper.js';
14
+ import { getTransferFunctionHash } from './RenderWindow/resourceSharingHelper.js';
14
15
  import { v as vtkPolyDataVS } from './glsl/vtkPolyDataVS.glsl.js';
15
16
  import { v as vtkPolyDataFS } from './glsl/vtkPolyDataFS.glsl.js';
16
17
  import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
@@ -554,6 +555,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
554
555
  publicAPI.renderPieceDraw(ren, actor);
555
556
  publicAPI.renderPieceFinish(ren, actor);
556
557
  };
558
+ publicAPI.computeBounds = (ren, actor) => {
559
+ if (!publicAPI.getInput()) {
560
+ uninitializeBounds(model.bounds);
561
+ return;
562
+ }
563
+ model.bounds = publicAPI.getInput().getBounds();
564
+ };
557
565
  publicAPI.updateBufferObjects = (ren, actor) => {
558
566
  // Rebuild buffers if needed
559
567
  if (publicAPI.getNeedToRebuildBufferObjects(ren, actor)) {
@@ -577,20 +585,19 @@ function vtkOpenGLImageMapper(publicAPI, model) {
577
585
  const iComps = actorProperty.getIndependentComponents();
578
586
  const numIComps = iComps ? numComp : 1;
579
587
  const textureHeight = iComps ? 2 * numIComps : 1;
580
- const colorTransferFunctions = [];
581
- for (let component = 0; component < numIComps; ++component) {
582
- colorTransferFunctions.push(actorProperty.getRGBTransferFunction(component));
583
- }
584
- const cfunToString = getTransferFunctionsHash(colorTransferFunctions, iComps, numIComps);
585
- const firstColorTransferFunc = actorProperty.getRGBTransferFunction();
586
- const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(firstColorTransferFunc);
588
+ const colorTransferFunc = actorProperty.getRGBTransferFunction();
589
+ const cfunToString = getTransferFunctionHash(colorTransferFunc, iComps, numIComps);
590
+ const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
587
591
  const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== cfunToString;
588
592
  if (reBuildC) {
589
593
  model.colorTexture = vtkOpenGLTexture.newInstance({
590
594
  resizable: true
591
595
  });
592
596
  model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
593
- const cWidth = 1024;
597
+ let cWidth = model.renderable.getColorTextureWidth();
598
+ if (cWidth <= 0) {
599
+ cWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
600
+ }
594
601
  const cSize = cWidth * textureHeight * 3;
595
602
  const cTable = new Uint8ClampedArray(cSize);
596
603
  // set interpolation on the texture based on property setting
@@ -601,7 +608,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
601
608
  model.colorTexture.setMinificationFilter(Filter.LINEAR);
602
609
  model.colorTexture.setMagnificationFilter(Filter.LINEAR);
603
610
  }
604
- if (firstColorTransferFunc) {
611
+ if (colorTransferFunc) {
605
612
  const tmpTable = new Float32Array(cWidth * 3);
606
613
  for (let c = 0; c < numIComps; c++) {
607
614
  const cfun = actorProperty.getRGBTransferFunction(c);
@@ -628,13 +635,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
628
635
  }
629
636
  model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
630
637
  }
631
- if (firstColorTransferFunc) {
632
- model._openGLRenderWindow.setGraphicsResourceForObject(firstColorTransferFunc, model.colorTexture, cfunToString);
633
- if (firstColorTransferFunc !== model._colorTransferFunc) {
634
- model._openGLRenderWindow.registerGraphicsResourceUser(firstColorTransferFunc, publicAPI);
638
+ if (colorTransferFunc) {
639
+ model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, cfunToString);
640
+ if (colorTransferFunc !== model._colorTransferFunc) {
641
+ model._openGLRenderWindow.registerGraphicsResourceUser(colorTransferFunc, publicAPI);
635
642
  model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
636
643
  }
637
- model._colorTransferFunc = firstColorTransferFunc;
644
+ model._colorTransferFunc = colorTransferFunc;
638
645
  }
639
646
  } else {
640
647
  model.colorTexture = cTex.oglObject;
@@ -643,17 +650,16 @@ function vtkOpenGLImageMapper(publicAPI, model) {
643
650
  // Build piecewise function buffer. This buffer is used either
644
651
  // for component weighting or opacity, depending on whether we're
645
652
  // rendering components independently or not.
646
- const opacityFunctions = [];
647
- for (let component = 0; component < numIComps; ++component) {
648
- opacityFunctions.push(actorProperty.getPiecewiseFunction(component));
649
- }
650
- const pwfunToString = getTransferFunctionsHash(opacityFunctions, iComps, numIComps);
651
- const firstPwFunc = actorProperty.getPiecewiseFunction();
652
- const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
653
+ const pwFunc = actorProperty.getPiecewiseFunction();
654
+ const pwfunToString = getTransferFunctionHash(pwFunc, iComps, numIComps);
655
+ const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
653
656
  // rebuild opacity tfun?
654
657
  const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== pwfunToString;
655
658
  if (reBuildPwf) {
656
- const pwfWidth = 1024;
659
+ let pwfWidth = model.renderable.getOpacityTextureWidth();
660
+ if (pwfWidth <= 0) {
661
+ pwfWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
662
+ }
657
663
  const pwfSize = pwfWidth * textureHeight;
658
664
  const pwfTable = new Uint8ClampedArray(pwfSize);
659
665
  model.pwfTexture = vtkOpenGLTexture.newInstance({
@@ -668,7 +674,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
668
674
  model.pwfTexture.setMinificationFilter(Filter.LINEAR);
669
675
  model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
670
676
  }
671
- if (firstPwFunc) {
677
+ if (pwFunc) {
672
678
  const pwfFloatTable = new Float32Array(pwfSize);
673
679
  const tmpTable = new Float32Array(pwfWidth);
674
680
  for (let c = 0; c < numIComps; ++c) {
@@ -699,13 +705,13 @@ function vtkOpenGLImageMapper(publicAPI, model) {
699
705
  pwfTable.fill(255.0);
700
706
  model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
701
707
  }
702
- if (firstPwFunc) {
703
- model._openGLRenderWindow.setGraphicsResourceForObject(firstPwFunc, model.pwfTexture, pwfunToString);
704
- if (firstPwFunc !== model._pwFunc) {
705
- model._openGLRenderWindow.registerGraphicsResourceUser(firstPwFunc, publicAPI);
708
+ if (pwFunc) {
709
+ model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, pwfunToString);
710
+ if (pwFunc !== model._pwFunc) {
711
+ model._openGLRenderWindow.registerGraphicsResourceUser(pwFunc, publicAPI);
706
712
  model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
707
713
  }
708
- model._pwFunc = firstPwFunc;
714
+ model._pwFunc = pwFunc;
709
715
  }
710
716
  } else {
711
717
  model.pwfTexture = pwfTex.oglObject;
@@ -863,10 +869,25 @@ function vtkOpenGLImageMapper(publicAPI, model) {
863
869
  vtkErrorMacro('Reformat slicing not yet supported.');
864
870
  }
865
871
 
872
+ /**
873
+ *
874
+ * Fetch the ranges of the source volume, `imgScalars`, and use them when
875
+ * creating the texture. Whilst the pre-calculated ranges may not be
876
+ * strictly correct for the slice, it is guaranteed to be within the
877
+ * source volume's range.
878
+ *
879
+ * There is a significant performance improvement by pre-setting the range
880
+ * of the scalars array particularly when scrolling through the source
881
+ * volume as there is no need to calculate the range of the slice scalar.
882
+ *
883
+ * @type{ import("../../../interfaces").vtkRange[] }
884
+ */
885
+ const ranges = imgScalars.getRanges();
886
+
866
887
  // Don't share this resource as `scalars` is created in this function
867
888
  // so it is impossible to share
868
889
  model.openGLTexture.resetFormatAndType();
869
- model.openGLTexture.create2DFilterableFromRaw(dims[0], dims[1], numComp, imgScalars.getDataType(), scalars, model.renderable.getPreferSizeOverAccuracy?.());
890
+ model.openGLTexture.create2DFilterableFromRaw(dims[0], dims[1], numComp, imgScalars.getDataType(), scalars, model.renderable.getPreferSizeOverAccuracy?.(), ranges);
870
891
  model.openGLTexture.activate();
871
892
  model.openGLTexture.sendParameters();
872
893
  model.openGLTexture.deactivate();
@@ -912,7 +933,10 @@ function vtkOpenGLImageMapper(publicAPI, model) {
912
933
  const toString = `${labelOutlineThicknessArray.join('-')}`;
913
934
  const reBuildL = !lTex?.oglObject?.getHandle() || lTex?.hash !== toString;
914
935
  if (reBuildL) {
915
- const lWidth = 1024;
936
+ let lWidth = model.renderable.getLabelOutlineTextureWidth();
937
+ if (lWidth <= 0) {
938
+ lWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
939
+ }
916
940
  const lHeight = 1;
917
941
  const lSize = lWidth * lHeight;
918
942
  const lTable = new Uint8Array(lSize);