@kitware/vtk.js 32.0.1 → 32.1.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.
- package/Common/DataModel/Box.d.ts +2 -1
- package/Common/DataModel/Box.js +2 -1
- package/Common/DataModel/Cone.d.ts +2 -6
- package/Common/DataModel/Cone.js +2 -1
- package/Common/DataModel/Cylinder.d.ts +3 -2
- package/Common/DataModel/Cylinder.js +2 -1
- package/Common/DataModel/ImageData.d.ts +0 -1
- package/Common/DataModel/ImageData.js +2 -2
- package/Common/DataModel/ImplicitBoolean.js +5 -4
- package/Common/DataModel/ImplicitFunction.d.ts +68 -0
- package/Common/DataModel/ImplicitFunction.js +60 -0
- package/Common/DataModel/Plane.d.ts +2 -1
- package/Common/DataModel/Plane.js +2 -1
- package/Common/DataModel/Sphere.d.ts +10 -17
- package/Common/DataModel/Sphere.js +11 -19
- package/Rendering/OpenGL/ImageCPRMapper.js +90 -66
- package/Rendering/OpenGL/ImageMapper.js +3 -9
- package/Rendering/OpenGL/ImageResliceMapper.js +9 -17
- package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.d.ts +34 -0
- package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.js +14 -0
- package/Rendering/OpenGL/Texture.d.ts +26 -0
- package/Rendering/OpenGL/Texture.js +124 -68
- package/Rendering/OpenGL/VolumeMapper.js +21 -18
- package/index.d.ts +2 -0
- package/package.json +1 -1
|
@@ -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
|
|
165
|
-
if (
|
|
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.
|
|
177
|
-
model.
|
|
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
|
|
191
|
-
|
|
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
|
-
|
|
196
|
-
|
|
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
|
-
|
|
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
|
|
231
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
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 =
|
|
913
|
-
model.colorTexture =
|
|
914
|
-
model.pwfTexture =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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 =
|
|
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 =
|
|
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
|
/**
|