@kitware/vtk.js 33.0.0-beta.4 → 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.
- package/BREAKING_CHANGES.md +0 -3
- package/Common/Core/ScalarsToColors/Constants.js +7 -2
- package/Common/Core/ScalarsToColors.js +3 -1
- package/Rendering/Core/Actor.d.ts +20 -5
- package/Rendering/Core/Actor.js +68 -5
- package/Rendering/Core/ColorTransferFunction.js +26 -35
- package/Rendering/Core/ImageCPRMapper.d.ts +20 -1
- package/Rendering/Core/ImageCPRMapper.js +2 -1
- package/Rendering/Core/ImageProperty.d.ts +1 -20
- package/Rendering/Core/ImageProperty.js +5 -7
- package/Rendering/Core/ImageResliceMapper.d.ts +20 -1
- package/Rendering/Core/ImageResliceMapper.js +2 -1
- package/Rendering/Core/ImageSlice.d.ts +23 -7
- package/Rendering/Core/ImageSlice.js +68 -9
- package/Rendering/Core/Mapper.js +8 -16
- package/Rendering/Core/Prop3D.d.ts +2 -39
- package/Rendering/Core/Prop3D.js +2 -81
- package/Rendering/Core/ScalarBarActor.js +4 -2
- package/Rendering/Core/Volume.d.ts +20 -5
- package/Rendering/Core/Volume.js +70 -2
- package/Rendering/Core/VolumeMapper/Constants.d.ts +7 -0
- package/Rendering/Core/VolumeMapper/Constants.js +8 -2
- package/Rendering/Core/VolumeMapper.d.ts +173 -16
- package/Rendering/Core/VolumeMapper.js +51 -16
- package/Rendering/Core/VolumeProperty/Constants.d.ts +3 -12
- package/Rendering/Core/VolumeProperty/Constants.js +4 -11
- package/Rendering/Core/VolumeProperty.d.ts +5 -140
- package/Rendering/Core/VolumeProperty.js +7 -54
- package/Rendering/OpenGL/ImageCPRMapper.js +21 -30
- package/Rendering/OpenGL/ImageMapper.js +27 -27
- package/Rendering/OpenGL/ImageResliceMapper.js +183 -271
- package/Rendering/OpenGL/PolyDataMapper.js +8 -1
- package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.d.ts +3 -3
- package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.js +5 -8
- package/Rendering/OpenGL/VolumeMapper.js +784 -722
- package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
- package/Rendering/WebGPU/VolumePassFSQ.js +2 -2
- package/index.d.ts +0 -1
- package/macros2.js +1 -1
- package/package.json +1 -1
- package/Interaction/Manipulators/KeyboardCameraManipulator.d.ts +0 -113
|
@@ -13,7 +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,
|
|
16
|
+
import { getImageDataHash, getTransferFunctionHash } from './RenderWindow/resourceSharingHelper.js';
|
|
17
17
|
import { v as vtkImageResliceMapperVS } from './glsl/vtkImageResliceMapperVS.glsl.js';
|
|
18
18
|
import { v as vtkImageResliceMapperFS } from './glsl/vtkImageResliceMapperFS.glsl.js';
|
|
19
19
|
import { Filter } from './Texture/Constants.js';
|
|
@@ -49,43 +49,8 @@ function safeMatrixMultiply(matrixArray, matrixType, tmpMat) {
|
|
|
49
49
|
function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
50
50
|
// Set our className
|
|
51
51
|
model.classHierarchy.push('vtkOpenGLImageResliceMapper');
|
|
52
|
-
|
|
53
|
-
// Associate a reference counter to each graphics resource
|
|
54
|
-
const graphicsResourceReferenceCount = new Map();
|
|
55
|
-
function decreaseGraphicsResourceCount(openGLRenderWindow, coreObject) {
|
|
56
|
-
if (!coreObject) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const oldCount = graphicsResourceReferenceCount.get(coreObject) ?? 0;
|
|
60
|
-
const newCount = oldCount - 1;
|
|
61
|
-
if (newCount <= 0) {
|
|
62
|
-
openGLRenderWindow.unregisterGraphicsResourceUser(coreObject, publicAPI);
|
|
63
|
-
graphicsResourceReferenceCount.delete(coreObject);
|
|
64
|
-
} else {
|
|
65
|
-
graphicsResourceReferenceCount.set(coreObject, newCount);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function increaseGraphicsResourceCount(openGLRenderWindow, coreObject) {
|
|
69
|
-
if (!coreObject) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const oldCount = graphicsResourceReferenceCount.get(coreObject) ?? 0;
|
|
73
|
-
const newCount = oldCount + 1;
|
|
74
|
-
graphicsResourceReferenceCount.set(coreObject, newCount);
|
|
75
|
-
if (oldCount <= 0) {
|
|
76
|
-
openGLRenderWindow.registerGraphicsResourceUser(coreObject, publicAPI);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
function replaceGraphicsResource(openGLRenderWindow, oldResourceCoreObject, newResourceCoreObject) {
|
|
80
|
-
if (oldResourceCoreObject === newResourceCoreObject) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
decreaseGraphicsResourceCount(openGLRenderWindow, oldResourceCoreObject);
|
|
84
|
-
increaseGraphicsResourceCount(openGLRenderWindow, newResourceCoreObject);
|
|
85
|
-
}
|
|
86
52
|
function unregisterGraphicsResources(renderWindow) {
|
|
87
|
-
|
|
88
|
-
[...graphicsResourceReferenceCount.keys()].forEach(coreObject => renderWindow.unregisterGraphicsResourceUser(coreObject, publicAPI));
|
|
53
|
+
[model._scalars, model._colorTransferFunc, model._pwFunc].forEach(coreObject => renderWindow.unregisterGraphicsResourceUser(coreObject, publicAPI));
|
|
89
54
|
}
|
|
90
55
|
publicAPI.buildPass = prepass => {
|
|
91
56
|
if (prepass) {
|
|
@@ -145,28 +110,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
145
110
|
type: 'StartEvent'
|
|
146
111
|
});
|
|
147
112
|
model.renderable.update();
|
|
148
|
-
|
|
149
|
-
model.
|
|
150
|
-
for (let inputIndex = 0; inputIndex < numberOfInputs; ++inputIndex) {
|
|
151
|
-
const imageData = model.renderable.getInputData(inputIndex);
|
|
152
|
-
if (imageData && !imageData.isDeleted()) {
|
|
153
|
-
model.currentValidInputs.push({
|
|
154
|
-
imageData,
|
|
155
|
-
inputIndex
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
const numberOfValidInputs = model.currentValidInputs.length;
|
|
160
|
-
if (numberOfValidInputs <= 0) {
|
|
113
|
+
model.currentInput = model.renderable.getInputData();
|
|
114
|
+
if (!model.currentInput) {
|
|
161
115
|
vtkErrorMacro('No input!');
|
|
162
116
|
return;
|
|
163
117
|
}
|
|
164
|
-
|
|
165
|
-
// Number of components
|
|
166
|
-
const firstImageData = model.currentValidInputs[0].imageData;
|
|
167
|
-
const firstScalars = firstImageData.getPointData().getScalars();
|
|
168
|
-
model.multiTexturePerVolumeEnabled = numberOfValidInputs > 1;
|
|
169
|
-
model.numberOfComponents = model.multiTexturePerVolumeEnabled ? numberOfValidInputs : firstScalars.getNumberOfComponents();
|
|
170
118
|
publicAPI.updateResliceGeometry();
|
|
171
119
|
publicAPI.renderPieceStart(ren, actor);
|
|
172
120
|
publicAPI.renderPieceDraw(ren, actor);
|
|
@@ -178,35 +126,17 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
178
126
|
publicAPI.renderPieceStart = (ren, actor) => {
|
|
179
127
|
// make sure the BOs are up to date
|
|
180
128
|
publicAPI.updateBufferObjects(ren, actor);
|
|
181
|
-
|
|
182
|
-
// Update filters for scalar textures
|
|
183
|
-
const actorProperties = actor.getProperties();
|
|
184
|
-
model.currentValidInputs.forEach(_ref => {
|
|
185
|
-
let {
|
|
186
|
-
inputIndex
|
|
187
|
-
} = _ref;
|
|
188
|
-
const actorProperty = actorProperties[inputIndex];
|
|
189
|
-
const interpolationType = actorProperty.getInterpolationType();
|
|
190
|
-
const scalarTexture = model.scalarTextures[inputIndex];
|
|
191
|
-
if (interpolationType === InterpolationType.NEAREST) {
|
|
192
|
-
scalarTexture.setMinificationFilter(Filter.NEAREST);
|
|
193
|
-
scalarTexture.setMagnificationFilter(Filter.NEAREST);
|
|
194
|
-
} else {
|
|
195
|
-
scalarTexture.setMinificationFilter(Filter.LINEAR);
|
|
196
|
-
scalarTexture.setMagnificationFilter(Filter.LINEAR);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// Update color and opacity texture filters
|
|
201
|
-
const firstValidInput = model.currentValidInputs[0];
|
|
202
|
-
const firstProperty = actorProperties[firstValidInput.inputIndex];
|
|
203
|
-
const iType = firstProperty.getInterpolationType();
|
|
129
|
+
const iType = actor.getProperty().getInterpolationType();
|
|
204
130
|
if (iType === InterpolationType.NEAREST) {
|
|
131
|
+
model.openGLTexture.setMinificationFilter(Filter.NEAREST);
|
|
132
|
+
model.openGLTexture.setMagnificationFilter(Filter.NEAREST);
|
|
205
133
|
model.colorTexture.setMinificationFilter(Filter.NEAREST);
|
|
206
134
|
model.colorTexture.setMagnificationFilter(Filter.NEAREST);
|
|
207
135
|
model.pwfTexture.setMinificationFilter(Filter.NEAREST);
|
|
208
136
|
model.pwfTexture.setMagnificationFilter(Filter.NEAREST);
|
|
209
137
|
} else {
|
|
138
|
+
model.openGLTexture.setMinificationFilter(Filter.LINEAR);
|
|
139
|
+
model.openGLTexture.setMagnificationFilter(Filter.LINEAR);
|
|
210
140
|
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
211
141
|
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
212
142
|
model.pwfTexture.setMinificationFilter(Filter.LINEAR);
|
|
@@ -220,8 +150,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
220
150
|
const gl = model.context;
|
|
221
151
|
|
|
222
152
|
// render the texture
|
|
223
|
-
|
|
224
|
-
|
|
153
|
+
model.openGLTexture.activate();
|
|
154
|
+
model.colorTexture.activate();
|
|
155
|
+
model.pwfTexture.activate();
|
|
225
156
|
|
|
226
157
|
// update shaders if required
|
|
227
158
|
publicAPI.updateShaders(model.tris, ren, actor);
|
|
@@ -229,7 +160,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
229
160
|
// Finally draw
|
|
230
161
|
gl.drawArrays(gl.TRIANGLES, 0, model.tris.getCABO().getElementCount());
|
|
231
162
|
model.tris.getVAO().release();
|
|
232
|
-
|
|
163
|
+
model.openGLTexture.deactivate();
|
|
164
|
+
model.colorTexture.deactivate();
|
|
165
|
+
model.pwfTexture.deactivate();
|
|
233
166
|
};
|
|
234
167
|
publicAPI.renderPieceFinish = (ren, actor) => {};
|
|
235
168
|
publicAPI.updateBufferObjects = (ren, actor) => {
|
|
@@ -238,63 +171,57 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
238
171
|
publicAPI.buildBufferObjects(ren, actor);
|
|
239
172
|
}
|
|
240
173
|
};
|
|
241
|
-
publicAPI.getNeedToRebuildBufferObjects = (ren, actor) => model.VBOBuildTime.getMTime() < publicAPI.getMTime() || model.VBOBuildTime.getMTime() < actor.getMTime() || model.VBOBuildTime.getMTime() < model.renderable.getMTime() || model.VBOBuildTime.getMTime() < actor.getProperty(model.
|
|
242
|
-
let {
|
|
243
|
-
imageData
|
|
244
|
-
} = _ref2;
|
|
245
|
-
return model.VBOBuildTime.getMTime() < imageData.getMTime();
|
|
246
|
-
}) || model.VBOBuildTime.getMTime() < model.resliceGeom.getMTime() || model.scalarTextures.length !== model.currentValidInputs.length || !model.scalarTextures.every(texture => !!texture?.getHandle()) || !model.colorTexture?.getHandle() || !model.pwfTexture?.getHandle();
|
|
174
|
+
publicAPI.getNeedToRebuildBufferObjects = (ren, actor) => model.VBOBuildTime.getMTime() < publicAPI.getMTime() || model.VBOBuildTime.getMTime() < actor.getMTime() || model.VBOBuildTime.getMTime() < model.renderable.getMTime() || model.VBOBuildTime.getMTime() < actor.getProperty().getMTime() || model.VBOBuildTime.getMTime() < model.currentInput.getMTime() || model.VBOBuildTime.getMTime() < model.resliceGeom.getMTime() || !model.openGLTexture?.getHandle() || !model.colorTexture?.getHandle() || !model.pwfTexture?.getHandle();
|
|
247
175
|
publicAPI.buildBufferObjects = (ren, actor) => {
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
256
|
-
const scalarsHash = getImageDataHash(imageData, scalars);
|
|
257
|
-
const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== scalarsHash;
|
|
258
|
-
const actorProperty = actorProperties[component];
|
|
259
|
-
const updatedExtents = actorProperty.getUpdatedExtents();
|
|
260
|
-
const hasUpdatedExtents = !!updatedExtents.length;
|
|
261
|
-
if (reBuildTex && !hasUpdatedExtents) {
|
|
262
|
-
const newScalarTexture = vtkOpenGLTexture.newInstance();
|
|
263
|
-
newScalarTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
264
|
-
// Build the textures
|
|
265
|
-
const dims = imageData.getDimensions();
|
|
266
|
-
// Use norm16 for scalar texture if the extension is available
|
|
267
|
-
newScalarTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
|
|
268
|
-
newScalarTexture.resetFormatAndType();
|
|
269
|
-
newScalarTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars);
|
|
270
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, newScalarTexture, scalarsHash);
|
|
271
|
-
model.scalarTextures[component] = newScalarTexture;
|
|
272
|
-
} else {
|
|
273
|
-
model.scalarTextures[component] = tex.oglObject;
|
|
274
|
-
}
|
|
275
|
-
if (hasUpdatedExtents) {
|
|
276
|
-
// If hasUpdatedExtents, then the texture is partially updated.
|
|
277
|
-
// clear the array to acknowledge the update.
|
|
278
|
-
actorProperty.setUpdatedExtents([]);
|
|
279
|
-
const dims = imageData.getDimensions();
|
|
280
|
-
model.scalarTextures[component].create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, false, updatedExtents);
|
|
281
|
-
}
|
|
282
|
-
replaceGraphicsResource(model._openGLRenderWindow, model._scalarTexturesCore[component], scalars);
|
|
283
|
-
model._scalarTexturesCore[component] = scalars;
|
|
284
|
-
});
|
|
285
|
-
const firstValidInput = model.currentValidInputs[0];
|
|
286
|
-
const firstActorProperty = actorProperties[firstValidInput.inputIndex];
|
|
287
|
-
const iComps = firstActorProperty.getIndependentComponents();
|
|
288
|
-
const numIComps = iComps ? model.numberOfComponents : 1;
|
|
289
|
-
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
290
|
-
const colorTransferFunctions = [];
|
|
291
|
-
for (let component = 0; component < numIComps; ++component) {
|
|
292
|
-
colorTransferFunctions.push(firstActorProperty.getRGBTransferFunction(component));
|
|
176
|
+
const image = model.currentInput;
|
|
177
|
+
if (!image) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const scalars = image.getPointData()?.getScalars();
|
|
181
|
+
if (!scalars) {
|
|
182
|
+
return;
|
|
293
183
|
}
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
const
|
|
297
|
-
const
|
|
184
|
+
const numComp = scalars.getNumberOfComponents();
|
|
185
|
+
let toString = getImageDataHash(image, scalars);
|
|
186
|
+
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
187
|
+
const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== toString;
|
|
188
|
+
const updatedExtents = model.renderable.getUpdatedExtents();
|
|
189
|
+
const hasUpdatedExtents = !!updatedExtents.length;
|
|
190
|
+
if (reBuildTex && !hasUpdatedExtents) {
|
|
191
|
+
model.openGLTexture = vtkOpenGLTexture.newInstance();
|
|
192
|
+
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
193
|
+
// Build the image scalar texture
|
|
194
|
+
// Use norm16 for the 3D texture if the extension is available
|
|
195
|
+
model.openGLTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
|
|
196
|
+
model.openGLTexture.resetFormatAndType();
|
|
197
|
+
|
|
198
|
+
// Build the image scalar texture
|
|
199
|
+
const dims = image.getDimensions();
|
|
200
|
+
model.openGLTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, false, updatedExtents);
|
|
201
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, toString);
|
|
202
|
+
if (scalars !== model._scalars) {
|
|
203
|
+
model._openGLRenderWindow.registerGraphicsResourceUser(scalars, publicAPI);
|
|
204
|
+
model._openGLRenderWindow.unregisterGraphicsResourceUser(model._scalars, publicAPI);
|
|
205
|
+
}
|
|
206
|
+
model._scalars = scalars;
|
|
207
|
+
} else {
|
|
208
|
+
model.openGLTexture = tex.oglObject;
|
|
209
|
+
}
|
|
210
|
+
if (hasUpdatedExtents) {
|
|
211
|
+
// If hasUpdatedExtents, then the texture is partially updated.
|
|
212
|
+
// clear the array to acknowledge the update.
|
|
213
|
+
model.renderable.setUpdatedExtents([]);
|
|
214
|
+
const dims = image.getDimensions();
|
|
215
|
+
model.openGLTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, false, updatedExtents);
|
|
216
|
+
}
|
|
217
|
+
const ppty = actor.getProperty();
|
|
218
|
+
const iComps = ppty.getIndependentComponents();
|
|
219
|
+
const numIComps = iComps ? numComp : 1;
|
|
220
|
+
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
221
|
+
const colorTransferFunc = ppty.getRGBTransferFunction();
|
|
222
|
+
toString = getTransferFunctionHash(colorTransferFunc, iComps, numIComps);
|
|
223
|
+
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
|
|
224
|
+
const reBuildC = !cTex?.oglObject?.getHandle() || cTex?.hash !== toString;
|
|
298
225
|
if (reBuildC) {
|
|
299
226
|
let cWidth = model.renderable.getColorTextureWidth();
|
|
300
227
|
if (cWidth <= 0) {
|
|
@@ -302,12 +229,12 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
302
229
|
}
|
|
303
230
|
const cSize = cWidth * textureHeight * 3;
|
|
304
231
|
const cTable = new Uint8ClampedArray(cSize);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (
|
|
232
|
+
model.colorTexture = vtkOpenGLTexture.newInstance();
|
|
233
|
+
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
234
|
+
if (colorTransferFunc) {
|
|
308
235
|
const tmpTable = new Float32Array(cWidth * 3);
|
|
309
236
|
for (let c = 0; c < numIComps; c++) {
|
|
310
|
-
const cfun =
|
|
237
|
+
const cfun = ppty.getRGBTransferFunction(c);
|
|
311
238
|
const cRange = cfun.getRange();
|
|
312
239
|
cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1);
|
|
313
240
|
if (iComps) {
|
|
@@ -317,46 +244,41 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
317
244
|
}
|
|
318
245
|
} else {
|
|
319
246
|
for (let i = 0; i < cWidth * 3; i++) {
|
|
320
|
-
cTable[c * cWidth *
|
|
247
|
+
cTable[c * cWidth * 6 + i] = 255.0 * tmpTable[i];
|
|
321
248
|
}
|
|
322
249
|
}
|
|
323
250
|
}
|
|
324
|
-
|
|
325
|
-
|
|
251
|
+
model.colorTexture.resetFormatAndType();
|
|
252
|
+
model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
326
253
|
} else {
|
|
327
|
-
for (let
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
cTable[row * cWidth * 3 + column + 0] = opacity;
|
|
332
|
-
cTable[row * cWidth * 3 + column + 1] = opacity;
|
|
333
|
-
cTable[row * cWidth * 3 + column + 2] = opacity;
|
|
334
|
-
}
|
|
254
|
+
for (let i = 0; i < cWidth * 3; ++i) {
|
|
255
|
+
cTable[i] = 255.0 * i / ((cWidth - 1) * 3);
|
|
256
|
+
cTable[i + 1] = 255.0 * i / ((cWidth - 1) * 3);
|
|
257
|
+
cTable[i + 2] = 255.0 * i / ((cWidth - 1) * 3);
|
|
335
258
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
if (
|
|
340
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(
|
|
259
|
+
model.colorTexture.resetFormatAndType();
|
|
260
|
+
model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
261
|
+
}
|
|
262
|
+
if (colorTransferFunc) {
|
|
263
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, toString);
|
|
264
|
+
if (colorTransferFunc !== model._colorTransferFunc) {
|
|
265
|
+
model._openGLRenderWindow.registerGraphicsResourceUser(colorTransferFunc, publicAPI);
|
|
266
|
+
model._openGLRenderWindow.unregisterGraphicsResourceUser(model._colorTransferFunc, publicAPI);
|
|
267
|
+
}
|
|
268
|
+
model._colorTransferFunc = colorTransferFunc;
|
|
341
269
|
}
|
|
342
|
-
model.colorTexture = newColorTexture;
|
|
343
270
|
} else {
|
|
344
271
|
model.colorTexture = cTex.oglObject;
|
|
345
272
|
}
|
|
346
|
-
replaceGraphicsResource(model._openGLRenderWindow, model._colorTextureCore, firstColorTransferFunc);
|
|
347
|
-
model._colorTextureCore = firstColorTransferFunc;
|
|
348
273
|
|
|
349
274
|
// Build piecewise function buffer. This buffer is used either
|
|
350
275
|
// for component weighting or opacity, depending on whether we're
|
|
351
276
|
// rendering components independently or not.
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const
|
|
357
|
-
const firstPwFunc = firstActorProperty.getPiecewiseFunction();
|
|
358
|
-
const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
|
|
359
|
-
const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== opacityFuncHash;
|
|
277
|
+
const pwFunc = ppty.getPiecewiseFunction();
|
|
278
|
+
toString = getTransferFunctionHash(pwFunc, iComps, numIComps);
|
|
279
|
+
const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
|
|
280
|
+
// rebuild opacity tfun?
|
|
281
|
+
const reBuildPwf = !pwfTex?.oglObject?.getHandle() || pwfTex?.hash !== toString;
|
|
360
282
|
if (reBuildPwf) {
|
|
361
283
|
let pwfWidth = model.renderable.getOpacityTextureWidth();
|
|
362
284
|
if (pwfWidth <= 0) {
|
|
@@ -364,13 +286,13 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
364
286
|
}
|
|
365
287
|
const pwfSize = pwfWidth * textureHeight;
|
|
366
288
|
const pwfTable = new Uint8ClampedArray(pwfSize);
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
if (
|
|
289
|
+
model.pwfTexture = vtkOpenGLTexture.newInstance();
|
|
290
|
+
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
291
|
+
if (pwFunc) {
|
|
370
292
|
const pwfFloatTable = new Float32Array(pwfSize);
|
|
371
293
|
const tmpTable = new Float32Array(pwfWidth);
|
|
372
294
|
for (let c = 0; c < numIComps; ++c) {
|
|
373
|
-
const pwfun =
|
|
295
|
+
const pwfun = ppty.getPiecewiseFunction(c);
|
|
374
296
|
if (pwfun === null) {
|
|
375
297
|
// Piecewise constant max if no function supplied for this component
|
|
376
298
|
pwfFloatTable.fill(1.0);
|
|
@@ -385,28 +307,30 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
385
307
|
}
|
|
386
308
|
} else {
|
|
387
309
|
for (let i = 0; i < pwfWidth; i++) {
|
|
388
|
-
pwfFloatTable[i] = tmpTable[i];
|
|
310
|
+
pwfFloatTable[c * pwfWidth * 2 + i] = tmpTable[i];
|
|
389
311
|
}
|
|
390
312
|
}
|
|
391
313
|
}
|
|
392
314
|
}
|
|
393
|
-
|
|
394
|
-
|
|
315
|
+
model.pwfTexture.resetFormatAndType();
|
|
316
|
+
model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
|
|
395
317
|
} else {
|
|
396
318
|
// default is opaque
|
|
397
319
|
pwfTable.fill(255.0);
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
if (
|
|
402
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(
|
|
320
|
+
model.pwfTexture.resetFormatAndType();
|
|
321
|
+
model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
|
|
322
|
+
}
|
|
323
|
+
if (pwFunc) {
|
|
324
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, toString);
|
|
325
|
+
if (pwFunc !== model._pwFunc) {
|
|
326
|
+
model._openGLRenderWindow.registerGraphicsResourceUser(pwFunc, publicAPI);
|
|
327
|
+
model._openGLRenderWindow.unregisterGraphicsResourceUser(model._pwFunc, publicAPI);
|
|
328
|
+
}
|
|
329
|
+
model._pwFunc = pwFunc;
|
|
403
330
|
}
|
|
404
|
-
model.pwfTexture = newOpacityTexture;
|
|
405
331
|
} else {
|
|
406
332
|
model.pwfTexture = pwfTex.oglObject;
|
|
407
333
|
}
|
|
408
|
-
replaceGraphicsResource(model._openGLRenderWindow, model._pwfTextureCore, firstPwFunc);
|
|
409
|
-
model._pwfTextureCore = firstPwFunc;
|
|
410
334
|
const vboString = `${model.resliceGeom.getMTime()}A${model.renderable.getSlabThickness()}`;
|
|
411
335
|
if (!model.tris.getCABO().getElementCount() || model.VBOBuildString !== vboString) {
|
|
412
336
|
const points = vtkDataArray.newInstance({
|
|
@@ -467,12 +391,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
467
391
|
};
|
|
468
392
|
publicAPI.setMapperShaderParameters = (cellBO, ren, actor) => {
|
|
469
393
|
const program = cellBO.getProgram();
|
|
470
|
-
const firstImageData = model.currentValidInputs[0].imageData;
|
|
471
394
|
if (cellBO.getCABO().getElementCount() && (model.VBOBuildTime.getMTime() > cellBO.getAttributeUpdateTime().getMTime() || cellBO.getShaderSourceTime().getMTime() > cellBO.getAttributeUpdateTime().getMTime())) {
|
|
472
395
|
// Set the 3D texture
|
|
473
|
-
|
|
474
|
-
program.setUniformi(
|
|
475
|
-
}
|
|
396
|
+
if (program.isUniformUsed('texture1')) {
|
|
397
|
+
program.setUniformi('texture1', model.openGLTexture.getTextureUnit());
|
|
398
|
+
}
|
|
476
399
|
|
|
477
400
|
// Set the plane vertex attributes
|
|
478
401
|
if (program.isAttributeUsed('vertexWC')) {
|
|
@@ -491,7 +414,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
491
414
|
program.setUniformf('slabThickness', model.renderable.getSlabThickness());
|
|
492
415
|
}
|
|
493
416
|
if (program.isUniformUsed('spacing')) {
|
|
494
|
-
program.setUniform3fv('spacing',
|
|
417
|
+
program.setUniform3fv('spacing', model.currentInput.getSpacing());
|
|
495
418
|
}
|
|
496
419
|
if (program.isUniformUsed('slabType')) {
|
|
497
420
|
program.setUniformi('slabType', model.renderable.getSlabType());
|
|
@@ -507,8 +430,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
507
430
|
|
|
508
431
|
// Set the world->texture matrix
|
|
509
432
|
if (program.isUniformUsed('WCTCMatrix')) {
|
|
510
|
-
const
|
|
511
|
-
|
|
433
|
+
const image = model.currentInput;
|
|
434
|
+
const dim = image.getDimensions();
|
|
435
|
+
mat4.copy(model.tmpMat4, image.getIndexToWorld());
|
|
512
436
|
mat4.translate(model.tmpMat4, model.tmpMat4, [-0.5, -0.5, -0.5]);
|
|
513
437
|
mat4.scale(model.tmpMat4, model.tmpMat4, dim);
|
|
514
438
|
mat4.invert(model.tmpMat4, model.tmpMat4);
|
|
@@ -557,8 +481,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
557
481
|
};
|
|
558
482
|
publicAPI.setPropertyShaderParameters = (cellBO, ren, actor) => {
|
|
559
483
|
const program = cellBO.getProgram();
|
|
560
|
-
const
|
|
561
|
-
const opacity =
|
|
484
|
+
const ppty = actor.getProperty();
|
|
485
|
+
const opacity = ppty.getOpacity();
|
|
562
486
|
program.setUniformf('opacity', opacity);
|
|
563
487
|
|
|
564
488
|
// Component mix
|
|
@@ -567,56 +491,53 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
567
491
|
// - 2 comps => LA
|
|
568
492
|
// - 3 comps => RGB + opacity from pwf
|
|
569
493
|
// - 4 comps => RGBA
|
|
570
|
-
const numComp = model.
|
|
571
|
-
const iComps =
|
|
494
|
+
const numComp = model.openGLTexture.getComponents();
|
|
495
|
+
const iComps = ppty.getIndependentComponents();
|
|
572
496
|
if (iComps) {
|
|
573
497
|
for (let i = 0; i < numComp; ++i) {
|
|
574
|
-
program.setUniformf(`mix${i}`,
|
|
498
|
+
program.setUniformf(`mix${i}`, ppty.getComponentWeight(i));
|
|
575
499
|
}
|
|
576
500
|
}
|
|
577
501
|
|
|
502
|
+
// Color opacity map
|
|
503
|
+
const volInfo = model.openGLTexture.getVolumeInfo();
|
|
504
|
+
|
|
578
505
|
// three levels of shift scale combined into one
|
|
579
506
|
// for performance in the fragment shader
|
|
580
|
-
for (let
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
const
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
const volScale = volInfo.scale[volInfoIndex];
|
|
587
|
-
const volOffset = volInfo.offset[volInfoIndex];
|
|
588
|
-
const target = iComps ? component : 0;
|
|
589
|
-
|
|
590
|
-
// color shift/scale
|
|
591
|
-
let cw = firstPpty.getColorWindow();
|
|
592
|
-
let cl = firstPpty.getColorLevel();
|
|
593
|
-
const cfun = firstPpty.getRGBTransferFunction(target);
|
|
594
|
-
if (cfun && firstPpty.getUseLookupTableScalarRange()) {
|
|
507
|
+
for (let i = 0; i < numComp; i++) {
|
|
508
|
+
let cw = ppty.getColorWindow();
|
|
509
|
+
let cl = ppty.getColorLevel();
|
|
510
|
+
const target = iComps ? i : 0;
|
|
511
|
+
const cfun = ppty.getRGBTransferFunction(target);
|
|
512
|
+
if (cfun && ppty.getUseLookupTableScalarRange()) {
|
|
595
513
|
const cRange = cfun.getRange();
|
|
596
514
|
cw = cRange[1] - cRange[0];
|
|
597
515
|
cl = 0.5 * (cRange[1] + cRange[0]);
|
|
598
516
|
}
|
|
599
|
-
const
|
|
600
|
-
const
|
|
601
|
-
program.setUniformf(`cshift${
|
|
602
|
-
program.setUniformf(`cscale${
|
|
517
|
+
const scale = volInfo.scale[i] / cw;
|
|
518
|
+
const shift = (volInfo.offset[i] - cl) / cw + 0.5;
|
|
519
|
+
program.setUniformf(`cshift${i}`, shift);
|
|
520
|
+
program.setUniformf(`cscale${i}`, scale);
|
|
521
|
+
}
|
|
522
|
+
const texColorUnit = model.colorTexture.getTextureUnit();
|
|
523
|
+
program.setUniformi('colorTexture1', texColorUnit);
|
|
603
524
|
|
|
604
|
-
|
|
525
|
+
// pwf shift/scale
|
|
526
|
+
for (let i = 0; i < numComp; i++) {
|
|
605
527
|
let pwfScale = 1.0;
|
|
606
528
|
let pwfShift = 0.0;
|
|
607
|
-
const
|
|
529
|
+
const target = iComps ? i : 0;
|
|
530
|
+
const pwfun = ppty.getPiecewiseFunction(target);
|
|
608
531
|
if (pwfun) {
|
|
609
532
|
const pwfRange = pwfun.getRange();
|
|
610
533
|
const length = pwfRange[1] - pwfRange[0];
|
|
611
534
|
const mid = 0.5 * (pwfRange[0] + pwfRange[1]);
|
|
612
|
-
pwfScale =
|
|
613
|
-
pwfShift = (
|
|
535
|
+
pwfScale = volInfo.scale[i] / length;
|
|
536
|
+
pwfShift = (volInfo.offset[i] - mid) / length + 0.5;
|
|
614
537
|
}
|
|
615
|
-
program.setUniformf(`pwfshift${
|
|
616
|
-
program.setUniformf(`pwfscale${
|
|
538
|
+
program.setUniformf(`pwfshift${i}`, pwfShift);
|
|
539
|
+
program.setUniformf(`pwfscale${i}`, pwfScale);
|
|
617
540
|
}
|
|
618
|
-
const texColorUnit = model.colorTexture.getTextureUnit();
|
|
619
|
-
program.setUniformi('colorTexture1', texColorUnit);
|
|
620
541
|
const texOpacityUnit = model.pwfTexture.getTextureUnit();
|
|
621
542
|
program.setUniformi('pwfTexture1', texOpacityUnit);
|
|
622
543
|
|
|
@@ -630,7 +551,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
630
551
|
// input modified
|
|
631
552
|
// light complexity changed
|
|
632
553
|
// render pass shader replacement changed
|
|
633
|
-
const
|
|
554
|
+
const tNumComp = model.openGLTexture.getComponents();
|
|
555
|
+
const iComp = actor.getProperty().getIndependentComponents();
|
|
634
556
|
const slabTh = model.renderable.getSlabThickness();
|
|
635
557
|
const slabType = model.renderable.getSlabType();
|
|
636
558
|
const slabTrap = model.renderable.getSlabTrapezoidIntegration();
|
|
@@ -640,10 +562,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
640
562
|
if (!model.currentRenderPass && model.lastRenderPassShaderReplacement || model.currentRenderPass && model.currentRenderPass.getShaderReplacement() !== model.lastRenderPassShaderReplacement) {
|
|
641
563
|
needRebuild = true;
|
|
642
564
|
}
|
|
643
|
-
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest ||
|
|
565
|
+
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram()?.getHandle() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp || model.lastSlabThickness !== slabTh || model.lastSlabType !== slabType || model.lastSlabTrapezoidIntegration !== slabTrap) {
|
|
644
566
|
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
|
|
645
|
-
model.
|
|
646
|
-
model.lastMultiTexturePerVolumeEnabled = model.multiTexturePerVolumeEnabled;
|
|
567
|
+
model.lastTextureComponents = tNumComp;
|
|
647
568
|
model.lastIndependentComponents = iComp;
|
|
648
569
|
model.lastSlabThickness = slabTh;
|
|
649
570
|
model.lastSlabType = slabType;
|
|
@@ -677,9 +598,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
677
598
|
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Dec', tcoordVSDec).result;
|
|
678
599
|
const tcoordVSImpl = ['fragTexCoord = (WCTCMatrix * vertexWC).xyz;'];
|
|
679
600
|
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Impl', tcoordVSImpl).result;
|
|
680
|
-
const tNumComp = model.
|
|
681
|
-
const iComps = actor.getProperty(
|
|
682
|
-
let tcoordFSDec = ['in vec3 fragTexCoord;',
|
|
601
|
+
const tNumComp = model.openGLTexture.getComponents();
|
|
602
|
+
const iComps = actor.getProperty().getIndependentComponents();
|
|
603
|
+
let tcoordFSDec = ['in vec3 fragTexCoord;', 'uniform highp sampler3D texture1;', 'uniform mat4 WCTCMatrix;',
|
|
683
604
|
// color shift and scale
|
|
684
605
|
'uniform float cshift0;', 'uniform float cscale0;',
|
|
685
606
|
// pwf shift and scale
|
|
@@ -690,18 +611,6 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
690
611
|
'uniform float opacity;',
|
|
691
612
|
// background color
|
|
692
613
|
'uniform vec4 backgroundColor;'];
|
|
693
|
-
|
|
694
|
-
// Function to sample texture
|
|
695
|
-
tcoordFSDec.push('vec4 rawSampleTexture(vec3 pos) {');
|
|
696
|
-
if (!model.multiTexturePerVolumeEnabled) {
|
|
697
|
-
tcoordFSDec.push('return texture(volumeTexture[0], pos);', '}');
|
|
698
|
-
} else {
|
|
699
|
-
tcoordFSDec.push('vec4 rawSample;');
|
|
700
|
-
for (let component = 0; component < model.scalarTextures.length; ++component) {
|
|
701
|
-
tcoordFSDec.push(`rawSample[${component}] = texture(volumeTexture[${component}], pos)[0];`);
|
|
702
|
-
}
|
|
703
|
-
tcoordFSDec.push('return rawSample;', '}');
|
|
704
|
-
}
|
|
705
614
|
if (iComps) {
|
|
706
615
|
for (let comp = 1; comp < tNumComp; comp++) {
|
|
707
616
|
tcoordFSDec = tcoordFSDec.concat([
|
|
@@ -737,14 +646,14 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
737
646
|
tcoordFSDec = tcoordFSDec.concat(['vec4 compositeValue(vec4 currVal, vec4 valToComp, int trapezoid)', '{', ' vec4 retVal = vec4(1.0);', ' if (slabType == 0) // min', ' {', ' retVal = min(currVal, valToComp);', ' }', ' else if (slabType == 1) // max', ' {', ' retVal = max(currVal, valToComp);', ' }', ' else if (slabType == 3) // sum', ' {', ' retVal = currVal + (trapezoid > 0 ? 0.5 * valToComp : valToComp); ', ' }', ' else // mean', ' {', ' retVal = currVal + (trapezoid > 0 ? 0.5 * valToComp : valToComp); ', ' }', ' return retVal;', '}']);
|
|
738
647
|
}
|
|
739
648
|
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Dec', tcoordFSDec).result;
|
|
740
|
-
let tcoordFSImpl = ['if (any(greaterThan(fragTexCoord, vec3(1.0))) || any(lessThan(fragTexCoord, vec3(0.0))))', '{', ' // set the background color and exit', ' gl_FragData[0] = backgroundColor;', ' return;', '}', 'vec4 tvalue =
|
|
649
|
+
let tcoordFSImpl = ['if (any(greaterThan(fragTexCoord, vec3(1.0))) || any(lessThan(fragTexCoord, vec3(0.0))))', '{', ' // set the background color and exit', ' gl_FragData[0] = backgroundColor;', ' return;', '}', 'vec4 tvalue = texture(texture1, fragTexCoord);'];
|
|
741
650
|
if (slabThickness > 0.0) {
|
|
742
|
-
tcoordFSImpl = tcoordFSImpl.concat(['// Get the first and last samples', 'int numSlices = 1;', 'float scaling = min(min(spacing.x, spacing.y), spacing.z) * 0.5;', 'vec3 normalxspacing = scaling * normalWCVSOutput;', 'float distTraveled = length(normalxspacing);', 'int trapezoid = 0;', 'while (distTraveled < slabThickness * 0.5)', '{', ' distTraveled += length(normalxspacing);', ' float fnumSlices = float(numSlices);', ' if (distTraveled > slabThickness * 0.5)', ' {', ' // Before stepping outside the slab, sample at the boundaries', ' normalxspacing = normalWCVSOutput * slabThickness * 0.5 / fnumSlices;', ' trapezoid = slabTrapezoid;', ' }', ' vec3 fragTCoordNeg = (WCTCMatrix * vec4(vertexWCVSOutput.xyz - fnumSlices * normalxspacing * vboScaling, 1.0)).xyz;', ' if (!any(greaterThan(fragTCoordNeg, vec3(1.0))) && !any(lessThan(fragTCoordNeg, vec3(0.0))))', ' {', ' vec4 newVal =
|
|
651
|
+
tcoordFSImpl = tcoordFSImpl.concat(['// Get the first and last samples', 'int numSlices = 1;', 'float scaling = min(min(spacing.x, spacing.y), spacing.z) * 0.5;', 'vec3 normalxspacing = scaling * normalWCVSOutput;', 'float distTraveled = length(normalxspacing);', 'int trapezoid = 0;', 'while (distTraveled < slabThickness * 0.5)', '{', ' distTraveled += length(normalxspacing);', ' float fnumSlices = float(numSlices);', ' if (distTraveled > slabThickness * 0.5)', ' {', ' // Before stepping outside the slab, sample at the boundaries', ' normalxspacing = normalWCVSOutput * slabThickness * 0.5 / fnumSlices;', ' trapezoid = slabTrapezoid;', ' }', ' vec3 fragTCoordNeg = (WCTCMatrix * vec4(vertexWCVSOutput.xyz - fnumSlices * normalxspacing * vboScaling, 1.0)).xyz;', ' if (!any(greaterThan(fragTCoordNeg, vec3(1.0))) && !any(lessThan(fragTCoordNeg, vec3(0.0))))', ' {', ' vec4 newVal = texture(texture1, fragTCoordNeg);', ' tvalue = compositeValue(tvalue, newVal, trapezoid);', ' numSlices += 1;', ' }', ' vec3 fragTCoordPos = (WCTCMatrix * vec4(vertexWCVSOutput.xyz + fnumSlices * normalxspacing * vboScaling, 1.0)).xyz;', ' if (!any(greaterThan(fragTCoordNeg, vec3(1.0))) && !any(lessThan(fragTCoordNeg, vec3(0.0))))', ' {', ' vec4 newVal = texture(texture1, fragTCoordPos);', ' tvalue = compositeValue(tvalue, newVal, trapezoid);', ' numSlices += 1;', ' }', '}', '// Finally, if slab type is *mean*, divide the sum by the numSlices', 'if (slabType == 2)', '{', ' tvalue = tvalue / float(numSlices);', '}']);
|
|
743
652
|
}
|
|
744
653
|
if (iComps) {
|
|
745
654
|
const rgba = ['r', 'g', 'b', 'a'];
|
|
746
655
|
for (let comp = 0; comp < tNumComp; ++comp) {
|
|
747
|
-
tcoordFSImpl = tcoordFSImpl.concat([`vec3 tcolor${comp} = texture2D(colorTexture1, vec2(tvalue.${rgba[comp]} * cscale${comp} + cshift${comp}, height${comp})).rgb;`, `float compWeight${comp} = mix${comp} * texture2D(pwfTexture1, vec2(tvalue.${rgba[comp]} * pwfscale${comp} + pwfshift${comp}, height${comp})).r;`]);
|
|
656
|
+
tcoordFSImpl = tcoordFSImpl.concat([`vec3 tcolor${comp} = mix${comp} * texture2D(colorTexture1, vec2(tvalue.${rgba[comp]} * cscale${comp} + cshift${comp}, height${comp})).rgb;`, `float compWeight${comp} = mix${comp} * texture2D(pwfTexture1, vec2(tvalue.${rgba[comp]} * pwfscale${comp} + pwfshift${comp}, height${comp})).r;`]);
|
|
748
657
|
}
|
|
749
658
|
switch (tNumComp) {
|
|
750
659
|
case 1:
|
|
@@ -830,8 +739,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
830
739
|
}
|
|
831
740
|
publicAPI.updateResliceGeometry = () => {
|
|
832
741
|
let resGeomString = '';
|
|
833
|
-
const
|
|
834
|
-
const imageBounds =
|
|
742
|
+
const image = model.currentInput;
|
|
743
|
+
const imageBounds = image?.getBounds();
|
|
835
744
|
// Orthogonal slicing by default
|
|
836
745
|
let orthoSlicing = true;
|
|
837
746
|
let orthoAxis = 2;
|
|
@@ -843,11 +752,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
843
752
|
resGeomString = resGeomString.concat(`Plane${slicePlane.getMTime()}`);
|
|
844
753
|
// Compute a world-to-image-orientation matrix.
|
|
845
754
|
const w2io = mat3.create();
|
|
846
|
-
if (
|
|
847
|
-
resGeomString = resGeomString.concat(`Image${
|
|
755
|
+
if (image) {
|
|
756
|
+
resGeomString = resGeomString.concat(`Image${image.getMTime()}`);
|
|
848
757
|
// Ignore the translation component since we are
|
|
849
758
|
// using it on vectors rather than positions.
|
|
850
|
-
mat3.set(w2io, ...
|
|
759
|
+
mat3.set(w2io, ...image.getDirection());
|
|
851
760
|
mat3.invert(w2io, w2io);
|
|
852
761
|
}
|
|
853
762
|
// Check to see if we can bypass oblique slicing related bounds computation
|
|
@@ -860,14 +769,14 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
860
769
|
const plane = vtkPlane.newInstance();
|
|
861
770
|
plane.setNormal(0, 0, 1);
|
|
862
771
|
let bds = [0, 1, 0, 1, 0, 1];
|
|
863
|
-
if (
|
|
772
|
+
if (image) {
|
|
864
773
|
bds = imageBounds;
|
|
865
774
|
}
|
|
866
775
|
plane.setOrigin(bds[0], bds[2], 0.5 * (bds[5] + bds[4]));
|
|
867
776
|
model.renderable.setSlicePlane(plane);
|
|
868
777
|
resGeomString = resGeomString.concat(`Plane${slicePlane?.getMTime()}`);
|
|
869
|
-
if (
|
|
870
|
-
resGeomString = resGeomString.concat(`Image${
|
|
778
|
+
if (image) {
|
|
779
|
+
resGeomString = resGeomString.concat(`Image${image.getMTime()}`);
|
|
871
780
|
}
|
|
872
781
|
}
|
|
873
782
|
if (!model.resliceGeom || model.resliceGeomUpdateString !== resGeomString) {
|
|
@@ -880,7 +789,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
880
789
|
model.resliceGeom.getPointData().setNormals(slicePD.getPointData().getNormals());
|
|
881
790
|
} else if (slicePlane) {
|
|
882
791
|
if (!orthoSlicing) {
|
|
883
|
-
model.outlineFilter.setInputData(
|
|
792
|
+
model.outlineFilter.setInputData(image);
|
|
884
793
|
model.cutter.setInputConnection(model.outlineFilter.getOutputPort());
|
|
885
794
|
model.cutter.setCutFunction(slicePlane);
|
|
886
795
|
model.lineToSurfaceFilter.setInputConnection(model.cutter.getOutputPort());
|
|
@@ -913,9 +822,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
913
822
|
// Since the image-local normal is axis-aligned, we
|
|
914
823
|
// can quickly construct the cutting plane using indexToWorld transforms.
|
|
915
824
|
const ptsArray = new Float32Array(12);
|
|
916
|
-
const indexSpacePlaneOrigin =
|
|
825
|
+
const indexSpacePlaneOrigin = image.worldToIndex(slicePlane.getOrigin(), [0, 0, 0]);
|
|
917
826
|
const otherAxes = [(orthoAxis + 1) % 3, (orthoAxis + 2) % 3].sort();
|
|
918
|
-
const ext =
|
|
827
|
+
const ext = image.getSpatialExtent();
|
|
919
828
|
let ptIdx = 0;
|
|
920
829
|
for (let i = 0; i < 2; ++i) {
|
|
921
830
|
for (let j = 0; j < 2; ++j) {
|
|
@@ -925,7 +834,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
925
834
|
ptIdx += 3;
|
|
926
835
|
}
|
|
927
836
|
}
|
|
928
|
-
model.transform.setMatrix(
|
|
837
|
+
model.transform.setMatrix(image.getIndexToWorld());
|
|
929
838
|
model.transform.transformPoints(ptsArray, ptsArray);
|
|
930
839
|
const cellArray = new Uint16Array(8);
|
|
931
840
|
cellArray[0] = 3;
|
|
@@ -963,9 +872,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
963
872
|
model.resliceGeom?.modified();
|
|
964
873
|
}
|
|
965
874
|
};
|
|
966
|
-
publicAPI.
|
|
967
|
-
|
|
968
|
-
|
|
875
|
+
publicAPI.setOpenGLTexture = oglTex => {
|
|
876
|
+
if (oglTex) {
|
|
877
|
+
model.openGLTexture = oglTex;
|
|
878
|
+
model._externalOpenGLTexture = true;
|
|
879
|
+
}
|
|
969
880
|
};
|
|
970
881
|
publicAPI.delete = chain(() => {
|
|
971
882
|
if (model._openGLRenderWindow) {
|
|
@@ -984,21 +895,22 @@ const DEFAULT_VALUES = {
|
|
|
984
895
|
haveSeenDepthRequest: false,
|
|
985
896
|
lastHaveSeenDepthRequest: false,
|
|
986
897
|
lastIndependentComponents: false,
|
|
987
|
-
|
|
988
|
-
lastMultiTexturePerVolumeEnabled: false,
|
|
898
|
+
lastTextureComponents: 0,
|
|
989
899
|
lastSlabThickness: 0,
|
|
990
900
|
lastSlabTrapezoidIntegration: 0,
|
|
991
901
|
lastSlabType: -1,
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
_colorTextureCore: null,
|
|
996
|
-
pwfTexture: null,
|
|
997
|
-
_pwfTextureCore: null,
|
|
998
|
-
_externalOpenGLTexture: false,
|
|
902
|
+
openGLTexture: null,
|
|
903
|
+
colorTextureString: null,
|
|
904
|
+
pwfTextureString: null,
|
|
999
905
|
resliceGeom: null,
|
|
1000
906
|
resliceGeomUpdateString: null,
|
|
1001
|
-
tris: null
|
|
907
|
+
tris: null,
|
|
908
|
+
colorTexture: null,
|
|
909
|
+
pwfTexture: null,
|
|
910
|
+
_externalOpenGLTexture: false
|
|
911
|
+
// _scalars: null,
|
|
912
|
+
// _colorTransferFunc: null,
|
|
913
|
+
// _pwFunc: null,
|
|
1002
914
|
};
|
|
1003
915
|
|
|
1004
916
|
// ----------------------------------------------------------------------------
|
|
@@ -1012,7 +924,7 @@ function extend(publicAPI, model) {
|
|
|
1012
924
|
vtkReplacementShaderMapper.implementReplaceShaderCoincidentOffset(publicAPI, model, initialValues);
|
|
1013
925
|
vtkReplacementShaderMapper.implementBuildShadersWithReplacements(publicAPI, model, initialValues);
|
|
1014
926
|
model.tris = vtkHelper.newInstance();
|
|
1015
|
-
model.
|
|
927
|
+
model.openGLTexture = null;
|
|
1016
928
|
model.colorTexture = null;
|
|
1017
929
|
model.pwfTexture = null;
|
|
1018
930
|
model.VBOBuildTime = {};
|
|
@@ -1027,7 +939,7 @@ function extend(publicAPI, model) {
|
|
|
1027
939
|
model.cutter = vtkCutter.newInstance();
|
|
1028
940
|
model.lineToSurfaceFilter = vtkClosedPolyLineToSurfaceFilter.newInstance();
|
|
1029
941
|
model.transform = vtkTransform.newInstance();
|
|
1030
|
-
get(publicAPI, model, ['
|
|
942
|
+
get(publicAPI, model, ['openGLTexture']);
|
|
1031
943
|
|
|
1032
944
|
// Object methods
|
|
1033
945
|
vtkOpenGLImageResliceMapper(publicAPI, model);
|