@kitware/vtk.js 33.0.0-beta.3 → 33.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BREAKING_CHANGES.md +0 -3
- package/Common/Core/DataArray.d.ts +17 -0
- package/Common/Core/DataArray.js +36 -0
- package/Common/Core/ScalarsToColors/Constants.js +7 -2
- package/Common/Core/ScalarsToColors.js +3 -1
- package/Rendering/Core/AbstractImageMapper.d.ts +81 -0
- package/Rendering/Core/AbstractImageMapper.js +5 -2
- package/Rendering/Core/AbstractPicker.d.ts +13 -13
- package/Rendering/Core/AbstractPicker.js +1 -1
- package/Rendering/Core/Actor.d.ts +20 -5
- package/Rendering/Core/Actor.js +68 -5
- package/Rendering/Core/Actor2D.d.ts +22 -0
- package/Rendering/Core/Actor2D.js +1 -1
- package/Rendering/Core/CellPicker.js +4 -1
- package/Rendering/Core/ColorTransferFunction.js +26 -35
- package/Rendering/Core/ImageCPRMapper.d.ts +20 -1
- package/Rendering/Core/ImageCPRMapper.js +7 -5
- package/Rendering/Core/ImageResliceMapper.d.ts +20 -2
- package/Rendering/Core/ImageResliceMapper.js +7 -5
- 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/Viewport.js +13 -3
- 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 +243 -16
- package/Rendering/Core/VolumeMapper.js +60 -20
- package/Rendering/Core/VolumeProperty/Constants.d.ts +3 -12
- package/Rendering/Core/VolumeProperty/Constants.js +4 -11
- package/Rendering/Core/VolumeProperty.d.ts +4 -120
- package/Rendering/Core/VolumeProperty.js +4 -49
- package/Rendering/Misc/SynchronizableRenderWindow/BehaviorManager/CameraSynchronizer.js +2 -2
- package/Rendering/OpenGL/ImageCPRMapper.js +36 -29
- package/Rendering/OpenGL/ImageMapper.js +55 -31
- package/Rendering/OpenGL/ImageResliceMapper.js +191 -263
- 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/Renderer.js +1 -1
- package/Rendering/OpenGL/Texture.d.ts +29 -8
- package/Rendering/OpenGL/Texture.js +154 -23
- package/Rendering/OpenGL/VolumeMapper.js +792 -712
- package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
- package/Rendering/SceneGraph/ViewNode.js +12 -2
- package/Rendering/WebGPU/VolumePassFSQ.js +2 -2
- package/Rendering/WebXR/RenderWindowHelper.js +9 -0
- package/Widgets/Core/WidgetManager.d.ts +12 -1
- package/Widgets/Representations/WidgetRepresentation.d.ts +1 -7
- package/Widgets/Widgets3D/ResliceCursorWidget.d.ts +1 -8
- package/index.d.ts +0 -1
- package/macros2.js +1 -1
- package/package.json +11 -11
- 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,70 @@ 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
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
} = _ref3;
|
|
252
|
-
// rebuild the scalarTexture if the data has changed
|
|
253
|
-
const scalars = imageData.getPointData().getScalars();
|
|
254
|
-
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
255
|
-
const scalarsHash = getImageDataHash(imageData, scalars);
|
|
256
|
-
const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== scalarsHash;
|
|
257
|
-
if (reBuildTex) {
|
|
258
|
-
const newScalarTexture = vtkOpenGLTexture.newInstance();
|
|
259
|
-
newScalarTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
260
|
-
// Build the textures
|
|
261
|
-
const dims = imageData.getDimensions();
|
|
262
|
-
// Use norm16 for scalar texture if the extension is available
|
|
263
|
-
newScalarTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
|
|
264
|
-
newScalarTexture.resetFormatAndType();
|
|
265
|
-
newScalarTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars);
|
|
266
|
-
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, newScalarTexture, scalarsHash);
|
|
267
|
-
model.scalarTextures[component] = newScalarTexture;
|
|
268
|
-
} else {
|
|
269
|
-
model.scalarTextures[component] = tex.oglObject;
|
|
270
|
-
}
|
|
271
|
-
replaceGraphicsResource(model._openGLRenderWindow, model._scalarTexturesCore[component], scalars);
|
|
272
|
-
model._scalarTexturesCore[component] = scalars;
|
|
273
|
-
});
|
|
274
|
-
const firstValidInput = model.currentValidInputs[0];
|
|
275
|
-
const actorProperties = actor.getProperties();
|
|
276
|
-
const firstActorProperty = actorProperties[firstValidInput.inputIndex];
|
|
277
|
-
const iComps = firstActorProperty.getIndependentComponents();
|
|
278
|
-
const numIComps = iComps ? model.numberOfComponents : 1;
|
|
279
|
-
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
280
|
-
const colorTransferFunctions = [];
|
|
281
|
-
for (let component = 0; component < numIComps; ++component) {
|
|
282
|
-
colorTransferFunctions.push(firstActorProperty.getRGBTransferFunction(component));
|
|
176
|
+
const image = model.currentInput;
|
|
177
|
+
if (!image) {
|
|
178
|
+
return;
|
|
283
179
|
}
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
180
|
+
const scalars = image.getPointData()?.getScalars();
|
|
181
|
+
if (!scalars) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
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;
|
|
288
225
|
if (reBuildC) {
|
|
289
|
-
|
|
226
|
+
let cWidth = model.renderable.getColorTextureWidth();
|
|
227
|
+
if (cWidth <= 0) {
|
|
228
|
+
cWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
|
|
229
|
+
}
|
|
290
230
|
const cSize = cWidth * textureHeight * 3;
|
|
291
231
|
const cTable = new Uint8ClampedArray(cSize);
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
if (
|
|
232
|
+
model.colorTexture = vtkOpenGLTexture.newInstance();
|
|
233
|
+
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
234
|
+
if (colorTransferFunc) {
|
|
295
235
|
const tmpTable = new Float32Array(cWidth * 3);
|
|
296
236
|
for (let c = 0; c < numIComps; c++) {
|
|
297
|
-
const cfun =
|
|
237
|
+
const cfun = ppty.getRGBTransferFunction(c);
|
|
298
238
|
const cRange = cfun.getRange();
|
|
299
239
|
cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1);
|
|
300
240
|
if (iComps) {
|
|
@@ -304,57 +244,55 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
304
244
|
}
|
|
305
245
|
} else {
|
|
306
246
|
for (let i = 0; i < cWidth * 3; i++) {
|
|
307
|
-
cTable[c * cWidth *
|
|
247
|
+
cTable[c * cWidth * 6 + i] = 255.0 * tmpTable[i];
|
|
308
248
|
}
|
|
309
249
|
}
|
|
310
250
|
}
|
|
311
|
-
|
|
312
|
-
|
|
251
|
+
model.colorTexture.resetFormatAndType();
|
|
252
|
+
model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
313
253
|
} else {
|
|
314
|
-
for (let
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
cTable[row * cWidth * 3 + column + 0] = opacity;
|
|
319
|
-
cTable[row * cWidth * 3 + column + 1] = opacity;
|
|
320
|
-
cTable[row * cWidth * 3 + column + 2] = opacity;
|
|
321
|
-
}
|
|
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);
|
|
322
258
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
if (
|
|
327
|
-
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;
|
|
328
269
|
}
|
|
329
|
-
model.colorTexture = newColorTexture;
|
|
330
270
|
} else {
|
|
331
271
|
model.colorTexture = cTex.oglObject;
|
|
332
272
|
}
|
|
333
|
-
replaceGraphicsResource(model._openGLRenderWindow, model._colorTextureCore, firstColorTransferFunc);
|
|
334
|
-
model._colorTextureCore = firstColorTransferFunc;
|
|
335
273
|
|
|
336
274
|
// Build piecewise function buffer. This buffer is used either
|
|
337
275
|
// for component weighting or opacity, depending on whether we're
|
|
338
276
|
// rendering components independently or not.
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const
|
|
344
|
-
const firstPwFunc = firstActorProperty.getPiecewiseFunction();
|
|
345
|
-
const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(firstPwFunc);
|
|
346
|
-
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;
|
|
347
282
|
if (reBuildPwf) {
|
|
348
|
-
|
|
283
|
+
let pwfWidth = model.renderable.getOpacityTextureWidth();
|
|
284
|
+
if (pwfWidth <= 0) {
|
|
285
|
+
pwfWidth = model.context.getParameter(model.context.MAX_TEXTURE_SIZE);
|
|
286
|
+
}
|
|
349
287
|
const pwfSize = pwfWidth * textureHeight;
|
|
350
288
|
const pwfTable = new Uint8ClampedArray(pwfSize);
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (
|
|
289
|
+
model.pwfTexture = vtkOpenGLTexture.newInstance();
|
|
290
|
+
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
291
|
+
if (pwFunc) {
|
|
354
292
|
const pwfFloatTable = new Float32Array(pwfSize);
|
|
355
293
|
const tmpTable = new Float32Array(pwfWidth);
|
|
356
294
|
for (let c = 0; c < numIComps; ++c) {
|
|
357
|
-
const pwfun =
|
|
295
|
+
const pwfun = ppty.getPiecewiseFunction(c);
|
|
358
296
|
if (pwfun === null) {
|
|
359
297
|
// Piecewise constant max if no function supplied for this component
|
|
360
298
|
pwfFloatTable.fill(1.0);
|
|
@@ -369,28 +307,30 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
369
307
|
}
|
|
370
308
|
} else {
|
|
371
309
|
for (let i = 0; i < pwfWidth; i++) {
|
|
372
|
-
pwfFloatTable[i] = tmpTable[i];
|
|
310
|
+
pwfFloatTable[c * pwfWidth * 2 + i] = tmpTable[i];
|
|
373
311
|
}
|
|
374
312
|
}
|
|
375
313
|
}
|
|
376
314
|
}
|
|
377
|
-
|
|
378
|
-
|
|
315
|
+
model.pwfTexture.resetFormatAndType();
|
|
316
|
+
model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
|
|
379
317
|
} else {
|
|
380
318
|
// default is opaque
|
|
381
319
|
pwfTable.fill(255.0);
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
if (
|
|
386
|
-
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;
|
|
387
330
|
}
|
|
388
|
-
model.pwfTexture = newOpacityTexture;
|
|
389
331
|
} else {
|
|
390
332
|
model.pwfTexture = pwfTex.oglObject;
|
|
391
333
|
}
|
|
392
|
-
replaceGraphicsResource(model._openGLRenderWindow, model._pwfTextureCore, firstPwFunc);
|
|
393
|
-
model._pwfTextureCore = firstPwFunc;
|
|
394
334
|
const vboString = `${model.resliceGeom.getMTime()}A${model.renderable.getSlabThickness()}`;
|
|
395
335
|
if (!model.tris.getCABO().getElementCount() || model.VBOBuildString !== vboString) {
|
|
396
336
|
const points = vtkDataArray.newInstance({
|
|
@@ -451,12 +391,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
451
391
|
};
|
|
452
392
|
publicAPI.setMapperShaderParameters = (cellBO, ren, actor) => {
|
|
453
393
|
const program = cellBO.getProgram();
|
|
454
|
-
const firstImageData = model.currentValidInputs[0].imageData;
|
|
455
394
|
if (cellBO.getCABO().getElementCount() && (model.VBOBuildTime.getMTime() > cellBO.getAttributeUpdateTime().getMTime() || cellBO.getShaderSourceTime().getMTime() > cellBO.getAttributeUpdateTime().getMTime())) {
|
|
456
395
|
// Set the 3D texture
|
|
457
|
-
|
|
458
|
-
program.setUniformi(
|
|
459
|
-
}
|
|
396
|
+
if (program.isUniformUsed('texture1')) {
|
|
397
|
+
program.setUniformi('texture1', model.openGLTexture.getTextureUnit());
|
|
398
|
+
}
|
|
460
399
|
|
|
461
400
|
// Set the plane vertex attributes
|
|
462
401
|
if (program.isAttributeUsed('vertexWC')) {
|
|
@@ -475,7 +414,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
475
414
|
program.setUniformf('slabThickness', model.renderable.getSlabThickness());
|
|
476
415
|
}
|
|
477
416
|
if (program.isUniformUsed('spacing')) {
|
|
478
|
-
program.setUniform3fv('spacing',
|
|
417
|
+
program.setUniform3fv('spacing', model.currentInput.getSpacing());
|
|
479
418
|
}
|
|
480
419
|
if (program.isUniformUsed('slabType')) {
|
|
481
420
|
program.setUniformi('slabType', model.renderable.getSlabType());
|
|
@@ -491,8 +430,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
491
430
|
|
|
492
431
|
// Set the world->texture matrix
|
|
493
432
|
if (program.isUniformUsed('WCTCMatrix')) {
|
|
494
|
-
const
|
|
495
|
-
|
|
433
|
+
const image = model.currentInput;
|
|
434
|
+
const dim = image.getDimensions();
|
|
435
|
+
mat4.copy(model.tmpMat4, image.getIndexToWorld());
|
|
496
436
|
mat4.translate(model.tmpMat4, model.tmpMat4, [-0.5, -0.5, -0.5]);
|
|
497
437
|
mat4.scale(model.tmpMat4, model.tmpMat4, dim);
|
|
498
438
|
mat4.invert(model.tmpMat4, model.tmpMat4);
|
|
@@ -541,8 +481,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
541
481
|
};
|
|
542
482
|
publicAPI.setPropertyShaderParameters = (cellBO, ren, actor) => {
|
|
543
483
|
const program = cellBO.getProgram();
|
|
544
|
-
const
|
|
545
|
-
const opacity =
|
|
484
|
+
const ppty = actor.getProperty();
|
|
485
|
+
const opacity = ppty.getOpacity();
|
|
546
486
|
program.setUniformf('opacity', opacity);
|
|
547
487
|
|
|
548
488
|
// Component mix
|
|
@@ -551,56 +491,53 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
551
491
|
// - 2 comps => LA
|
|
552
492
|
// - 3 comps => RGB + opacity from pwf
|
|
553
493
|
// - 4 comps => RGBA
|
|
554
|
-
const numComp = model.
|
|
555
|
-
const iComps =
|
|
494
|
+
const numComp = model.openGLTexture.getComponents();
|
|
495
|
+
const iComps = ppty.getIndependentComponents();
|
|
556
496
|
if (iComps) {
|
|
557
497
|
for (let i = 0; i < numComp; ++i) {
|
|
558
|
-
program.setUniformf(`mix${i}`,
|
|
498
|
+
program.setUniformf(`mix${i}`, ppty.getComponentWeight(i));
|
|
559
499
|
}
|
|
560
500
|
}
|
|
561
501
|
|
|
502
|
+
// Color opacity map
|
|
503
|
+
const volInfo = model.openGLTexture.getVolumeInfo();
|
|
504
|
+
|
|
562
505
|
// three levels of shift scale combined into one
|
|
563
506
|
// for performance in the fragment shader
|
|
564
|
-
for (let
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
const
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
const volScale = volInfo.scale[volInfoIndex];
|
|
571
|
-
const volOffset = volInfo.offset[volInfoIndex];
|
|
572
|
-
const target = iComps ? component : 0;
|
|
573
|
-
|
|
574
|
-
// color shift/scale
|
|
575
|
-
let cw = firstPpty.getColorWindow();
|
|
576
|
-
let cl = firstPpty.getColorLevel();
|
|
577
|
-
const cfun = firstPpty.getRGBTransferFunction(target);
|
|
578
|
-
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()) {
|
|
579
513
|
const cRange = cfun.getRange();
|
|
580
514
|
cw = cRange[1] - cRange[0];
|
|
581
515
|
cl = 0.5 * (cRange[1] + cRange[0]);
|
|
582
516
|
}
|
|
583
|
-
const
|
|
584
|
-
const
|
|
585
|
-
program.setUniformf(`cshift${
|
|
586
|
-
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);
|
|
587
524
|
|
|
588
|
-
|
|
525
|
+
// pwf shift/scale
|
|
526
|
+
for (let i = 0; i < numComp; i++) {
|
|
589
527
|
let pwfScale = 1.0;
|
|
590
528
|
let pwfShift = 0.0;
|
|
591
|
-
const
|
|
529
|
+
const target = iComps ? i : 0;
|
|
530
|
+
const pwfun = ppty.getPiecewiseFunction(target);
|
|
592
531
|
if (pwfun) {
|
|
593
532
|
const pwfRange = pwfun.getRange();
|
|
594
533
|
const length = pwfRange[1] - pwfRange[0];
|
|
595
534
|
const mid = 0.5 * (pwfRange[0] + pwfRange[1]);
|
|
596
|
-
pwfScale =
|
|
597
|
-
pwfShift = (
|
|
535
|
+
pwfScale = volInfo.scale[i] / length;
|
|
536
|
+
pwfShift = (volInfo.offset[i] - mid) / length + 0.5;
|
|
598
537
|
}
|
|
599
|
-
program.setUniformf(`pwfshift${
|
|
600
|
-
program.setUniformf(`pwfscale${
|
|
538
|
+
program.setUniformf(`pwfshift${i}`, pwfShift);
|
|
539
|
+
program.setUniformf(`pwfscale${i}`, pwfScale);
|
|
601
540
|
}
|
|
602
|
-
const texColorUnit = model.colorTexture.getTextureUnit();
|
|
603
|
-
program.setUniformi('colorTexture1', texColorUnit);
|
|
604
541
|
const texOpacityUnit = model.pwfTexture.getTextureUnit();
|
|
605
542
|
program.setUniformi('pwfTexture1', texOpacityUnit);
|
|
606
543
|
|
|
@@ -614,7 +551,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
614
551
|
// input modified
|
|
615
552
|
// light complexity changed
|
|
616
553
|
// render pass shader replacement changed
|
|
617
|
-
const
|
|
554
|
+
const tNumComp = model.openGLTexture.getComponents();
|
|
555
|
+
const iComp = actor.getProperty().getIndependentComponents();
|
|
618
556
|
const slabTh = model.renderable.getSlabThickness();
|
|
619
557
|
const slabType = model.renderable.getSlabType();
|
|
620
558
|
const slabTrap = model.renderable.getSlabTrapezoidIntegration();
|
|
@@ -624,10 +562,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
624
562
|
if (!model.currentRenderPass && model.lastRenderPassShaderReplacement || model.currentRenderPass && model.currentRenderPass.getShaderReplacement() !== model.lastRenderPassShaderReplacement) {
|
|
625
563
|
needRebuild = true;
|
|
626
564
|
}
|
|
627
|
-
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) {
|
|
628
566
|
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
|
|
629
|
-
model.
|
|
630
|
-
model.lastMultiTexturePerVolumeEnabled = model.multiTexturePerVolumeEnabled;
|
|
567
|
+
model.lastTextureComponents = tNumComp;
|
|
631
568
|
model.lastIndependentComponents = iComp;
|
|
632
569
|
model.lastSlabThickness = slabTh;
|
|
633
570
|
model.lastSlabType = slabType;
|
|
@@ -661,9 +598,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
661
598
|
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Dec', tcoordVSDec).result;
|
|
662
599
|
const tcoordVSImpl = ['fragTexCoord = (WCTCMatrix * vertexWC).xyz;'];
|
|
663
600
|
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::TCoord::Impl', tcoordVSImpl).result;
|
|
664
|
-
const tNumComp = model.
|
|
665
|
-
const iComps = actor.getProperty(
|
|
666
|
-
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;',
|
|
667
604
|
// color shift and scale
|
|
668
605
|
'uniform float cshift0;', 'uniform float cscale0;',
|
|
669
606
|
// pwf shift and scale
|
|
@@ -674,18 +611,6 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
674
611
|
'uniform float opacity;',
|
|
675
612
|
// background color
|
|
676
613
|
'uniform vec4 backgroundColor;'];
|
|
677
|
-
|
|
678
|
-
// Function to sample texture
|
|
679
|
-
tcoordFSDec.push('vec4 rawSampleTexture(vec3 pos) {');
|
|
680
|
-
if (!model.multiTexturePerVolumeEnabled) {
|
|
681
|
-
tcoordFSDec.push('return texture(volumeTexture[0], pos);', '}');
|
|
682
|
-
} else {
|
|
683
|
-
tcoordFSDec.push('vec4 rawSample;');
|
|
684
|
-
for (let component = 0; component < model.scalarTextures.length; ++component) {
|
|
685
|
-
tcoordFSDec.push(`rawSample[${component}] = texture(volumeTexture[${component}], pos)[0];`);
|
|
686
|
-
}
|
|
687
|
-
tcoordFSDec.push('return rawSample;', '}');
|
|
688
|
-
}
|
|
689
614
|
if (iComps) {
|
|
690
615
|
for (let comp = 1; comp < tNumComp; comp++) {
|
|
691
616
|
tcoordFSDec = tcoordFSDec.concat([
|
|
@@ -721,14 +646,14 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
721
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;', '}']);
|
|
722
647
|
}
|
|
723
648
|
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::TCoord::Dec', tcoordFSDec).result;
|
|
724
|
-
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);'];
|
|
725
650
|
if (slabThickness > 0.0) {
|
|
726
|
-
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);', '}']);
|
|
727
652
|
}
|
|
728
653
|
if (iComps) {
|
|
729
654
|
const rgba = ['r', 'g', 'b', 'a'];
|
|
730
655
|
for (let comp = 0; comp < tNumComp; ++comp) {
|
|
731
|
-
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;`]);
|
|
732
657
|
}
|
|
733
658
|
switch (tNumComp) {
|
|
734
659
|
case 1:
|
|
@@ -814,8 +739,8 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
814
739
|
}
|
|
815
740
|
publicAPI.updateResliceGeometry = () => {
|
|
816
741
|
let resGeomString = '';
|
|
817
|
-
const
|
|
818
|
-
const imageBounds =
|
|
742
|
+
const image = model.currentInput;
|
|
743
|
+
const imageBounds = image?.getBounds();
|
|
819
744
|
// Orthogonal slicing by default
|
|
820
745
|
let orthoSlicing = true;
|
|
821
746
|
let orthoAxis = 2;
|
|
@@ -827,11 +752,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
827
752
|
resGeomString = resGeomString.concat(`Plane${slicePlane.getMTime()}`);
|
|
828
753
|
// Compute a world-to-image-orientation matrix.
|
|
829
754
|
const w2io = mat3.create();
|
|
830
|
-
if (
|
|
831
|
-
resGeomString = resGeomString.concat(`Image${
|
|
755
|
+
if (image) {
|
|
756
|
+
resGeomString = resGeomString.concat(`Image${image.getMTime()}`);
|
|
832
757
|
// Ignore the translation component since we are
|
|
833
758
|
// using it on vectors rather than positions.
|
|
834
|
-
mat3.set(w2io, ...
|
|
759
|
+
mat3.set(w2io, ...image.getDirection());
|
|
835
760
|
mat3.invert(w2io, w2io);
|
|
836
761
|
}
|
|
837
762
|
// Check to see if we can bypass oblique slicing related bounds computation
|
|
@@ -844,14 +769,14 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
844
769
|
const plane = vtkPlane.newInstance();
|
|
845
770
|
plane.setNormal(0, 0, 1);
|
|
846
771
|
let bds = [0, 1, 0, 1, 0, 1];
|
|
847
|
-
if (
|
|
772
|
+
if (image) {
|
|
848
773
|
bds = imageBounds;
|
|
849
774
|
}
|
|
850
775
|
plane.setOrigin(bds[0], bds[2], 0.5 * (bds[5] + bds[4]));
|
|
851
776
|
model.renderable.setSlicePlane(plane);
|
|
852
777
|
resGeomString = resGeomString.concat(`Plane${slicePlane?.getMTime()}`);
|
|
853
|
-
if (
|
|
854
|
-
resGeomString = resGeomString.concat(`Image${
|
|
778
|
+
if (image) {
|
|
779
|
+
resGeomString = resGeomString.concat(`Image${image.getMTime()}`);
|
|
855
780
|
}
|
|
856
781
|
}
|
|
857
782
|
if (!model.resliceGeom || model.resliceGeomUpdateString !== resGeomString) {
|
|
@@ -864,7 +789,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
864
789
|
model.resliceGeom.getPointData().setNormals(slicePD.getPointData().getNormals());
|
|
865
790
|
} else if (slicePlane) {
|
|
866
791
|
if (!orthoSlicing) {
|
|
867
|
-
model.outlineFilter.setInputData(
|
|
792
|
+
model.outlineFilter.setInputData(image);
|
|
868
793
|
model.cutter.setInputConnection(model.outlineFilter.getOutputPort());
|
|
869
794
|
model.cutter.setCutFunction(slicePlane);
|
|
870
795
|
model.lineToSurfaceFilter.setInputConnection(model.cutter.getOutputPort());
|
|
@@ -897,9 +822,9 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
897
822
|
// Since the image-local normal is axis-aligned, we
|
|
898
823
|
// can quickly construct the cutting plane using indexToWorld transforms.
|
|
899
824
|
const ptsArray = new Float32Array(12);
|
|
900
|
-
const indexSpacePlaneOrigin =
|
|
825
|
+
const indexSpacePlaneOrigin = image.worldToIndex(slicePlane.getOrigin(), [0, 0, 0]);
|
|
901
826
|
const otherAxes = [(orthoAxis + 1) % 3, (orthoAxis + 2) % 3].sort();
|
|
902
|
-
const ext =
|
|
827
|
+
const ext = image.getSpatialExtent();
|
|
903
828
|
let ptIdx = 0;
|
|
904
829
|
for (let i = 0; i < 2; ++i) {
|
|
905
830
|
for (let j = 0; j < 2; ++j) {
|
|
@@ -909,7 +834,7 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
909
834
|
ptIdx += 3;
|
|
910
835
|
}
|
|
911
836
|
}
|
|
912
|
-
model.transform.setMatrix(
|
|
837
|
+
model.transform.setMatrix(image.getIndexToWorld());
|
|
913
838
|
model.transform.transformPoints(ptsArray, ptsArray);
|
|
914
839
|
const cellArray = new Uint16Array(8);
|
|
915
840
|
cellArray[0] = 3;
|
|
@@ -947,9 +872,11 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
947
872
|
model.resliceGeom?.modified();
|
|
948
873
|
}
|
|
949
874
|
};
|
|
950
|
-
publicAPI.
|
|
951
|
-
|
|
952
|
-
|
|
875
|
+
publicAPI.setOpenGLTexture = oglTex => {
|
|
876
|
+
if (oglTex) {
|
|
877
|
+
model.openGLTexture = oglTex;
|
|
878
|
+
model._externalOpenGLTexture = true;
|
|
879
|
+
}
|
|
953
880
|
};
|
|
954
881
|
publicAPI.delete = chain(() => {
|
|
955
882
|
if (model._openGLRenderWindow) {
|
|
@@ -968,21 +895,22 @@ const DEFAULT_VALUES = {
|
|
|
968
895
|
haveSeenDepthRequest: false,
|
|
969
896
|
lastHaveSeenDepthRequest: false,
|
|
970
897
|
lastIndependentComponents: false,
|
|
971
|
-
|
|
972
|
-
lastMultiTexturePerVolumeEnabled: false,
|
|
898
|
+
lastTextureComponents: 0,
|
|
973
899
|
lastSlabThickness: 0,
|
|
974
900
|
lastSlabTrapezoidIntegration: 0,
|
|
975
901
|
lastSlabType: -1,
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
_colorTextureCore: null,
|
|
980
|
-
pwfTexture: null,
|
|
981
|
-
_pwfTextureCore: null,
|
|
982
|
-
_externalOpenGLTexture: false,
|
|
902
|
+
openGLTexture: null,
|
|
903
|
+
colorTextureString: null,
|
|
904
|
+
pwfTextureString: null,
|
|
983
905
|
resliceGeom: null,
|
|
984
906
|
resliceGeomUpdateString: null,
|
|
985
|
-
tris: null
|
|
907
|
+
tris: null,
|
|
908
|
+
colorTexture: null,
|
|
909
|
+
pwfTexture: null,
|
|
910
|
+
_externalOpenGLTexture: false
|
|
911
|
+
// _scalars: null,
|
|
912
|
+
// _colorTransferFunc: null,
|
|
913
|
+
// _pwFunc: null,
|
|
986
914
|
};
|
|
987
915
|
|
|
988
916
|
// ----------------------------------------------------------------------------
|
|
@@ -996,7 +924,7 @@ function extend(publicAPI, model) {
|
|
|
996
924
|
vtkReplacementShaderMapper.implementReplaceShaderCoincidentOffset(publicAPI, model, initialValues);
|
|
997
925
|
vtkReplacementShaderMapper.implementBuildShadersWithReplacements(publicAPI, model, initialValues);
|
|
998
926
|
model.tris = vtkHelper.newInstance();
|
|
999
|
-
model.
|
|
927
|
+
model.openGLTexture = null;
|
|
1000
928
|
model.colorTexture = null;
|
|
1001
929
|
model.pwfTexture = null;
|
|
1002
930
|
model.VBOBuildTime = {};
|
|
@@ -1011,7 +939,7 @@ function extend(publicAPI, model) {
|
|
|
1011
939
|
model.cutter = vtkCutter.newInstance();
|
|
1012
940
|
model.lineToSurfaceFilter = vtkClosedPolyLineToSurfaceFilter.newInstance();
|
|
1013
941
|
model.transform = vtkTransform.newInstance();
|
|
1014
|
-
get(publicAPI, model, ['
|
|
942
|
+
get(publicAPI, model, ['openGLTexture']);
|
|
1015
943
|
|
|
1016
944
|
// Object methods
|
|
1017
945
|
vtkOpenGLImageResliceMapper(publicAPI, model);
|