@kitware/vtk.js 32.0.1 → 32.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +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, 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 { registerOverride } from './ViewNodeFactory.js';
@@ -21,19 +22,6 @@ const {
21
22
  vtkErrorMacro
22
23
  } = macro;
23
24
 
24
- // ----------------------------------------------------------------------------
25
- // helper methods
26
- // ----------------------------------------------------------------------------
27
-
28
- function computeFnToString(property, fn, numberOfComponents) {
29
- const pwfun = fn.apply(property);
30
- if (pwfun) {
31
- const iComps = property.getIndependentComponents();
32
- return `${property.getMTime()}-${iComps}-${numberOfComponents}`;
33
- }
34
- return '0';
35
- }
36
-
37
25
  // ----------------------------------------------------------------------------
38
26
  // vtkOpenGLImageCPRMapper methods
39
27
  // ----------------------------------------------------------------------------
@@ -41,18 +29,22 @@ function computeFnToString(property, fn, numberOfComponents) {
41
29
  function vtkOpenGLImageCPRMapper(publicAPI, model) {
42
30
  // Set our className
43
31
  model.classHierarchy.push('vtkOpenGLImageCPRMapper');
32
+ function unregisterGraphicsResources(renderWindow) {
33
+ [model._scalars, model._colorTransferFunc, model._pwFunc].forEach(coreObject => renderWindow.unregisterGraphicsResourceUser(coreObject, publicAPI));
34
+ }
44
35
  publicAPI.buildPass = prepass => {
45
36
  if (prepass) {
46
37
  model.currentRenderPass = null;
47
38
  model.openGLImageSlice = publicAPI.getFirstAncestorOfType('vtkOpenGLImageSlice');
48
39
  model._openGLRenderer = publicAPI.getFirstAncestorOfType('vtkOpenGLRenderer');
40
+ const oldOglRenderWindow = model._openGLRenderWindow;
49
41
  model._openGLRenderWindow = model._openGLRenderer.getLastAncestorOfType('vtkOpenGLRenderWindow');
42
+ if (oldOglRenderWindow && !oldOglRenderWindow.isDeleted() && oldOglRenderWindow !== model._openGLRenderWindow) {
43
+ unregisterGraphicsResources(oldOglRenderWindow);
44
+ }
50
45
  model.context = model._openGLRenderWindow.getContext();
51
46
  model.openGLCamera = model._openGLRenderer.getViewNodeFor(model._openGLRenderer.getRenderable().getActiveCamera());
52
47
  model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
53
- model.volumeTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
54
- model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
55
- model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
56
48
  }
57
49
  };
58
50
  publicAPI.opaquePass = (prepass, renderPass) => {
@@ -128,22 +120,8 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
128
120
  if (publicAPI.getNeedToRebuildBufferObjects(ren, actor)) {
129
121
  publicAPI.buildBufferObjects(ren, actor);
130
122
  }
131
- };
132
- publicAPI.getNeedToRebuildBufferObjects = (ren, actor) => {
133
- // first do a coarse check
134
- // Note that the actor's mtime includes it's properties mtime
135
- const vmtime = model.VBOBuildTime.getMTime();
136
- if (vmtime < publicAPI.getMTime() || vmtime < model.renderable.getMTime() || vmtime < actor.getMTime() || vmtime < model.currentImageDataInput.getMTime() || vmtime < model.currentCenterlineInput.getMTime()) {
137
- return true;
138
- }
139
- return false;
140
- };
141
- publicAPI.buildBufferObjects = (ren, actor) => {
142
- const image = model.currentImageDataInput;
143
- const centerline = model.currentCenterlineInput;
144
- const actorProperty = actor.getProperty();
145
-
146
123
  // Set interpolation on the texture based on property setting
124
+ const actorProperty = actor.getProperty();
147
125
  if (actorProperty.getInterpolationType() === InterpolationType.NEAREST) {
148
126
  model.volumeTexture.setMinificationFilter(Filter.NEAREST);
149
127
  model.volumeTexture.setMagnificationFilter(Filter.NEAREST);
@@ -159,44 +137,64 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
159
137
  model.pwfTexture.setMinificationFilter(Filter.LINEAR);
160
138
  model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
161
139
  }
140
+ };
141
+ publicAPI.getNeedToRebuildBufferObjects = (ren, actor) => {
142
+ // first do a coarse check
143
+ // Note that the actor's mtime includes it's properties mtime
144
+ const vmtime = model.VBOBuildTime.getMTime();
145
+ return vmtime < publicAPI.getMTime() || vmtime < model.renderable.getMTime() || vmtime < actor.getMTime() || vmtime < model.currentImageDataInput.getMTime() || vmtime < model.currentCenterlineInput.getMTime() || !model.volumeTexture?.getHandle();
146
+ };
147
+ publicAPI.buildBufferObjects = (ren, actor) => {
148
+ const image = model.currentImageDataInput;
149
+ const centerline = model.currentCenterlineInput;
162
150
 
163
151
  // Rebuild the volumeTexture if the data has changed
164
- const imageTime = image.getMTime();
165
- if (model.volumeTextureTime !== imageTime) {
152
+ const scalars = image?.getPointData()?.getScalars();
153
+ if (!scalars) {
154
+ return;
155
+ }
156
+ const cachedScalarsEntry = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
157
+ const volumeTextureHash = getImageDataHash(image, scalars);
158
+ const reBuildTex = !cachedScalarsEntry?.oglObject?.getHandle() || cachedScalarsEntry?.hash !== volumeTextureHash;
159
+ if (reBuildTex) {
160
+ model.volumeTexture = vtkOpenGLTexture.newInstance();
161
+ model.volumeTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
166
162
  // Build the textures
167
163
  const dims = image.getDimensions();
168
- const scalars = image.getPointData().getScalars();
169
- if (!scalars) {
170
- return;
171
- }
172
164
  // Use norm16 for scalar texture if the extension is available
173
165
  model.volumeTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
174
- model.volumeTexture.releaseGraphicsResources(model._openGLRenderWindow);
175
166
  model.volumeTexture.resetFormatAndType();
176
- model.volumeTexture.create3DFilterableFromRaw(dims[0], dims[1], dims[2], scalars.getNumberOfComponents(), scalars.getDataType(), scalars.getData(), model.renderable.getPreferSizeOverAccuracy());
177
- model.volumeTextureTime = imageTime;
167
+ model.volumeTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, model.renderable.getPreferSizeOverAccuracy());
168
+ model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.volumeTexture, volumeTextureHash);
169
+ if (scalars !== model._scalars) {
170
+ model._openGLRenderWindow.registerGraphicsResourceUser(scalars, publicAPI);
171
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._scalars, publicAPI);
172
+ }
173
+ model._scalars = scalars;
174
+ } else {
175
+ model.volumeTexture = cachedScalarsEntry.oglObject;
178
176
  }
179
177
 
180
178
  // Rebuild the color texture if needed
181
- const scalars = image.getPointData() && image.getPointData().getScalars();
182
- if (!scalars) {
183
- return;
184
- }
185
179
  const numComp = scalars.getNumberOfComponents();
186
180
  const ppty = actor.getProperty();
187
181
  const iComps = ppty.getIndependentComponents();
188
182
  const numIComps = iComps ? numComp : 1;
189
183
  const textureHeight = iComps ? 2 * numIComps : 1;
190
- const cfunToString = computeFnToString(ppty, ppty.getRGBTransferFunction, numIComps);
191
- if (model.colorTextureString !== cfunToString) {
184
+ const colorTransferFunc = ppty.getRGBTransferFunction();
185
+ const colorTextureHash = getTransferFunctionHash(colorTransferFunc, iComps, numIComps);
186
+ const cachedColorEntry = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
187
+ const reBuildColorTexture = !cachedColorEntry?.oglObject?.getHandle() || cachedColorEntry?.hash !== colorTextureHash;
188
+ if (reBuildColorTexture) {
192
189
  const cWidth = 1024;
193
190
  const cSize = cWidth * textureHeight * 3;
194
191
  const cTable = new Uint8ClampedArray(cSize);
195
- let cfun = ppty.getRGBTransferFunction();
196
- if (cfun) {
192
+ model.colorTexture = vtkOpenGLTexture.newInstance();
193
+ model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
194
+ if (colorTransferFunc) {
197
195
  const tmpTable = new Float32Array(cWidth * 3);
198
196
  for (let c = 0; c < numIComps; c++) {
199
- cfun = ppty.getRGBTransferFunction(c);
197
+ const cfun = ppty.getRGBTransferFunction(c);
200
198
  const cRange = cfun.getRange();
201
199
  cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1);
202
200
  if (iComps) {
@@ -210,7 +208,6 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
210
208
  }
211
209
  }
212
210
  }
213
- model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
214
211
  model.colorTexture.resetFormatAndType();
215
212
  model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
216
213
  } else {
@@ -219,28 +216,39 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
219
216
  cTable[i + 1] = 255.0 * i / ((cWidth - 1) * 3);
220
217
  cTable[i + 2] = 255.0 * i / ((cWidth - 1) * 3);
221
218
  }
219
+ model.colorTexture.resetFormatAndType();
222
220
  model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
223
221
  }
224
- model.colorTextureString = cfunToString;
222
+ if (colorTransferFunc) {
223
+ model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, colorTextureHash);
224
+ if (colorTransferFunc !== model._colorTransferFunc) {
225
+ model._openGLRenderWindow.registerGraphicsResourceUser(colorTransferFunc, publicAPI);
226
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
227
+ }
228
+ model._colorTransferFunc = colorTransferFunc;
229
+ }
230
+ } else {
231
+ model.colorTexture = cachedColorEntry.oglObject;
225
232
  }
226
233
 
227
234
  // Build piecewise function buffer. This buffer is used either
228
235
  // for component weighting or opacity, depending on whether we're
229
236
  // rendering components independently or not.
230
- const pwfunToString = computeFnToString(ppty, ppty.getPiecewiseFunction, numIComps);
231
- if (model.pwfTextureString !== pwfunToString) {
237
+ const pwFunc = ppty.getPiecewiseFunction();
238
+ const pwfTextureHash = getTransferFunctionHash(pwFunc, iComps, numIComps);
239
+ const cachedPwfEntry = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
240
+ const reBuildPwf = !cachedPwfEntry?.oglObject?.getHandle() || cachedPwfEntry?.hash !== pwfTextureHash;
241
+ if (reBuildPwf) {
232
242
  const pwfWidth = 1024;
233
243
  const pwfSize = pwfWidth * textureHeight;
234
244
  const pwfTable = new Uint8ClampedArray(pwfSize);
235
- let pwfun = ppty.getPiecewiseFunction();
236
- // support case where pwfun is added/removed
237
- model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
238
- model.pwfTexture.resetFormatAndType();
239
- if (pwfun) {
245
+ model.pwfTexture = vtkOpenGLTexture.newInstance();
246
+ model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
247
+ if (pwFunc) {
240
248
  const pwfFloatTable = new Float32Array(pwfSize);
241
249
  const tmpTable = new Float32Array(pwfWidth);
242
250
  for (let c = 0; c < numIComps; ++c) {
243
- pwfun = ppty.getPiecewiseFunction(c);
251
+ const pwfun = ppty.getPiecewiseFunction(c);
244
252
  if (pwfun === null) {
245
253
  // Piecewise constant max if no function supplied for this component
246
254
  pwfFloatTable.fill(1.0);
@@ -260,13 +268,24 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
260
268
  }
261
269
  }
262
270
  }
271
+ model.pwfTexture.resetFormatAndType();
263
272
  model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
264
273
  } else {
265
274
  // default is opaque
266
275
  pwfTable.fill(255.0);
276
+ model.pwfTexture.resetFormatAndType();
267
277
  model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
268
278
  }
269
- model.pwfTextureString = pwfunToString;
279
+ if (pwFunc) {
280
+ model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, pwfTextureHash);
281
+ if (pwFunc !== model._pwFunc) {
282
+ model._openGLRenderWindow.registerGraphicsResourceUser(pwFunc, publicAPI);
283
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
284
+ }
285
+ model._pwFunc = pwFunc;
286
+ }
287
+ } else {
288
+ model.pwfTexture = cachedPwfEntry.oglObject;
270
289
  }
271
290
 
272
291
  // Rebuild the image vertices if needed
@@ -873,6 +892,11 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
873
892
  publicAPI.setCameraShaderParameters(cellBO, ren, actor);
874
893
  publicAPI.setPropertyShaderParameters(cellBO, ren, actor);
875
894
  };
895
+ publicAPI.delete = macro.chain(() => {
896
+ if (model._openGLRenderWindow) {
897
+ unregisterGraphicsResources(model._openGLRenderWindow);
898
+ }
899
+ }, publicAPI.delete);
876
900
  }
877
901
 
878
902
  // ----------------------------------------------------------------------------
@@ -882,11 +906,8 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
882
906
  const DEFAULT_VALUES = {
883
907
  currentRenderPass: null,
884
908
  volumeTexture: null,
885
- volumeTextureTime: 0,
886
909
  colorTexture: null,
887
- colorTextureString: null,
888
910
  pwfTexture: null,
889
- pwfTextureString: null,
890
911
  tris: null,
891
912
  lastHaveSeenDepthRequest: false,
892
913
  haveSeenDepthRequest: false,
@@ -894,6 +915,9 @@ const DEFAULT_VALUES = {
894
915
  lastIndependentComponents: 0,
895
916
  imagemat: null,
896
917
  imagematinv: null
918
+ // _scalars: null,
919
+ // _colorTransferFunc: null,
920
+ // _pwFunc: null,
897
921
  };
898
922
 
899
923
  // ----------------------------------------------------------------------------
@@ -909,9 +933,9 @@ function extend(publicAPI, model) {
909
933
  // Two inputs: one for the ImageData/Texture and one for the PolyData (centerline)
910
934
  macro.algo(publicAPI, model, 2, 0);
911
935
  model.tris = vtkHelper.newInstance();
912
- model.volumeTexture = vtkOpenGLTexture.newInstance();
913
- model.colorTexture = vtkOpenGLTexture.newInstance();
914
- model.pwfTexture = vtkOpenGLTexture.newInstance();
936
+ model.volumeTexture = null;
937
+ model.colorTexture = null;
938
+ model.pwfTexture = null;
915
939
  model.imagemat = mat4.identity(new Float64Array(16));
916
940
  model.imagematinv = mat4.identity(new Float64Array(16));
917
941
  model.VBOBuildTime = {};
@@ -11,6 +11,7 @@ import vtkViewNode from '../SceneGraph/ViewNode.js';
11
11
  import { Representation } from '../Core/Property/Constants.js';
12
12
  import { Filter, Wrap } from './Texture/Constants.js';
13
13
  import { InterpolationType } from '../Core/ImageProperty/Constants.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';
@@ -29,13 +30,6 @@ const {
29
30
  // helper methods
30
31
  // ----------------------------------------------------------------------------
31
32
 
32
- function computeFnToString(property, pwfun, numberOfComponents) {
33
- if (pwfun) {
34
- const iComps = property.getIndependentComponents();
35
- return `${pwfun.getMTime()}-${iComps}-${numberOfComponents}`;
36
- }
37
- return '0';
38
- }
39
33
  function splitStringOnEnter(inputString) {
40
34
  // Split the input string into an array of lines based on "Enter" (newline) characters
41
35
  // Remove any leading or trailing whitespace from each line and filter out empty lines
@@ -585,7 +579,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
585
579
  const numIComps = iComps ? numComp : 1;
586
580
  const textureHeight = iComps ? 2 * numIComps : 1;
587
581
  const colorTransferFunc = actorProperty.getRGBTransferFunction();
588
- const cfunToString = computeFnToString(actorProperty, colorTransferFunc, numIComps);
582
+ const cfunToString = getTransferFunctionHash(colorTransferFunc, iComps, numIComps);
589
583
  const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
590
584
  const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== cfunToString;
591
585
  if (reBuildC) {
@@ -647,7 +641,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
647
641
  // for component weighting or opacity, depending on whether we're
648
642
  // rendering components independently or not.
649
643
  const pwFunc = actorProperty.getPiecewiseFunction();
650
- const pwfunToString = computeFnToString(actorProperty, pwFunc, numIComps);
644
+ const pwfunToString = getTransferFunctionHash(pwFunc, iComps, numIComps);
651
645
  const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
652
646
  // rebuild opacity tfun?
653
647
  const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== pwfunToString;
@@ -13,6 +13,7 @@ import vtkReplacementShaderMapper from './ReplacementShaderMapper.js';
13
13
  import vtkShaderProgram from './ShaderProgram.js';
14
14
  import vtkTransform from '../../Common/Transform/Transform.js';
15
15
  import vtkViewNode from '../SceneGraph/ViewNode.js';
16
+ import { getImageDataHash, getTransferFunctionHash } from './RenderWindow/resourceSharingHelper.js';
16
17
  import { v as vtkImageResliceMapperVS } from './glsl/vtkImageResliceMapperVS.glsl.js';
17
18
  import { v as vtkImageResliceMapperFS } from './glsl/vtkImageResliceMapperFS.glsl.js';
18
19
  import { Filter } from './Texture/Constants.js';
@@ -31,13 +32,6 @@ const {
31
32
  // helper methods
32
33
  // ----------------------------------------------------------------------------
33
34
 
34
- function computeFnToString(property, pwfun, numberOfComponents) {
35
- if (pwfun) {
36
- const iComps = property.getIndependentComponents();
37
- return `${pwfun.getMTime()}-${iComps}-${numberOfComponents}`;
38
- }
39
- return '0';
40
- }
41
35
  function safeMatrixMultiply(matrixArray, matrixType, tmpMat) {
42
36
  matrixType.identity(tmpMat);
43
37
  return matrixArray.reduce((res, matrix, index) => {
@@ -188,7 +182,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
188
182
  return;
189
183
  }
190
184
  const numComp = scalars.getNumberOfComponents();
191
- let toString = `${image.getMTime()}A${scalars.getMTime()}`;
185
+ let toString = getImageDataHash(image, scalars);
192
186
  const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
193
187
  const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== toString;
194
188
  if (reBuildTex) {
@@ -200,14 +194,12 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
200
194
  model.openGLTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
201
195
  model.openGLTexture.resetFormatAndType();
202
196
  model.openGLTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars);
203
- if (scalars) {
204
- model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, toString);
205
- if (scalars !== model._scalars) {
206
- model._openGLRenderWindow.registerGraphicsResourceUser(scalars, publicAPI);
207
- model._openGLRenderWindow.unregisterGraphicsResourceUser(model._scalars, publicAPI);
208
- }
209
- model._scalars = scalars;
197
+ model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, toString);
198
+ if (scalars !== model._scalars) {
199
+ model._openGLRenderWindow.registerGraphicsResourceUser(scalars, publicAPI);
200
+ model._openGLRenderWindow.unregisterGraphicsResourceUser(model._scalars, publicAPI);
210
201
  }
202
+ model._scalars = scalars;
211
203
  } else {
212
204
  model.openGLTexture = tex.oglObject;
213
205
  }
@@ -216,7 +208,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
216
208
  const numIComps = iComps ? numComp : 1;
217
209
  const textureHeight = iComps ? 2 * numIComps : 1;
218
210
  const colorTransferFunc = ppty.getRGBTransferFunction();
219
- toString = computeFnToString(ppty, colorTransferFunc, numIComps);
211
+ toString = getTransferFunctionHash(colorTransferFunc, iComps, numIComps);
220
212
  const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
221
213
  const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== toString;
222
214
  if (reBuildC) {
@@ -269,7 +261,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
269
261
  // for component weighting or opacity, depending on whether we're
270
262
  // rendering components independently or not.
271
263
  const pwFunc = ppty.getPiecewiseFunction();
272
- toString = computeFnToString(ppty, pwFunc, numIComps);
264
+ toString = getTransferFunctionHash(pwFunc, iComps, numIComps);
273
265
  const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
274
266
  // rebuild opacity tfun?
275
267
  const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== toString;
@@ -0,0 +1,34 @@
1
+ import vtkImageData from '../../../Common/DataModel/ImageData';
2
+ import vtkDataArray from '../../../Common/Core/DataArray';
3
+ import { vtkObject } from '../../../interfaces';
4
+
5
+ /**
6
+ * Compute and return a hash than can be used for caching resources
7
+ *
8
+ * @param transferFunction The transfer function, it can be any vtkObject, but is usually a vtkTransferFunction
9
+ * @param useIndependentComponents A boolean taken from the image or volume property, using getIndependentComponents()
10
+ * @param numberOfComponents Taken from the data array, using getNumberOfComponents()
11
+ */
12
+ export function getTransferFunctionHash(
13
+ transferFunction: vtkObject | undefined,
14
+ useIndependentComponents: boolean,
15
+ numberOfComponents: number
16
+ ): string;
17
+
18
+ /**
19
+ * Compute and return a hash than can be used for caching resources
20
+ *
21
+ * @param image The image data that contains the scalars
22
+ * @param scalars The scalars used for rendering
23
+ */
24
+ export function getImageDataHash(
25
+ image: vtkImageData,
26
+ scalars: vtkDataArray
27
+ ): string;
28
+
29
+ declare const defaultExport: {
30
+ getTransferFunctionHash: typeof getTransferFunctionHash;
31
+ getImageDataHash: typeof getImageDataHash;
32
+ };
33
+
34
+ export default defaultExport;
@@ -0,0 +1,14 @@
1
+ // See typescript header for documentation
2
+
3
+ function getTransferFunctionHash(transferFunction, useIndependentComponents, numberOfComponents) {
4
+ return transferFunction ? `${transferFunction.getMTime()}-${useIndependentComponents}-${numberOfComponents}` : '0';
5
+ }
6
+ function getImageDataHash(image, scalars) {
7
+ return `${image.getMTime()}A${scalars.getMTime()}`;
8
+ }
9
+ var resourceSharingHelper = {
10
+ getTransferFunctionHash,
11
+ getImageDataHash
12
+ };
13
+
14
+ export { resourceSharingHelper as default, getImageDataHash, getTransferFunctionHash };
@@ -175,6 +175,23 @@ export interface vtkOpenGLTexture extends vtkViewNode {
175
175
  */
176
176
  getOpenGLWrapMode(vtktype: Wrap): any;
177
177
 
178
+ /**
179
+ * Updates the data array to match the required data type for OpenGL.
180
+ *
181
+ * This function takes the input data and converts it to the appropriate
182
+ * format required by the OpenGL texture, based on the specified data type.
183
+ *
184
+ * @param {string} dataType - The original data type of the input data.
185
+ * @param {Array} data - The input data array that needs to be updated.
186
+ * @param {boolean} [depth=false] - Indicates whether the data is a 3D array.
187
+ * @returns {Array} The updated data array that matches the OpenGL data type.
188
+ */
189
+ updateArrayDataTypeForGL(
190
+ dataType: VtkDataTypes,
191
+ data: any,
192
+ depth?: boolean
193
+ ): void;
194
+
178
195
  /**
179
196
  * Creates a 2D texture from raw data.
180
197
  * @param width The width of the texture.
@@ -323,6 +340,15 @@ export interface vtkOpenGLTexture extends vtkViewNode {
323
340
  * @returns {number} The maximum texture size.
324
341
  */
325
342
  getMaximumTextureSize(ctx: any): number;
343
+
344
+ /**
345
+ * Public API to disable half float usage.
346
+ * Half float is automatically enabled when creating the texture,
347
+ * but users may want to disable it in certain cases
348
+ * (e.g., streaming data where the full range is not yet available).
349
+ * @param useHalfFloat - whether to use half float
350
+ */
351
+ enableUseHalfFloat(useHalfFloat: boolean): void;
326
352
  }
327
353
 
328
354
  /**