@kitware/vtk.js 28.12.4 → 28.13.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/Imaging/Core/ImageReslice.js +21 -50
- package/Interaction/UI/FPSMonitor.js +1 -0
- package/Proxy/Core/View2DProxy.js +3 -0
- package/Rendering/Core/ImageProperty.js +14 -5
- package/Rendering/Core/Mapper2D.js +10 -0
- package/Rendering/Core/RenderWindow.js +17 -8
- package/Rendering/Core/VolumeProperty.js +20 -8
- package/Rendering/OpenGL/BufferObject.js +5 -2
- package/Rendering/OpenGL/Helper.js +1 -0
- package/Rendering/OpenGL/ImageMapper.js +77 -43
- package/Rendering/OpenGL/ImageResliceMapper.js +76 -40
- package/Rendering/OpenGL/PolyDataMapper.js +8 -0
- package/Rendering/OpenGL/PolyDataMapper2D.js +8 -0
- package/Rendering/OpenGL/RenderWindow.d.ts +37 -1
- package/Rendering/OpenGL/RenderWindow.js +84 -0
- package/Rendering/OpenGL/Renderer.js +7 -1
- package/Rendering/OpenGL/ShaderCache.js +23 -22
- package/Rendering/OpenGL/ShaderProgram.js +12 -2
- package/Rendering/OpenGL/Texture.js +9 -3
- package/Rendering/OpenGL/TextureUnitManager.js +5 -0
- package/Rendering/OpenGL/VolumeMapper.js +52 -11
- package/package.json +1 -1
|
@@ -29,7 +29,7 @@ function vtkImageReslice(publicAPI, model) {
|
|
|
29
29
|
const superClass = {
|
|
30
30
|
...publicAPI
|
|
31
31
|
};
|
|
32
|
-
|
|
32
|
+
const indexMatrix = mat4.identity(new Float64Array(16));
|
|
33
33
|
let optimizedTransform = null;
|
|
34
34
|
function getImageResliceSlabTrap(tmpPtr, inComponents, sampleCount, f) {
|
|
35
35
|
const n = sampleCount - 1;
|
|
@@ -218,7 +218,7 @@ function vtkImageReslice(publicAPI, model) {
|
|
|
218
218
|
let interpolationMode = model.interpolationMode;
|
|
219
219
|
model.usePermuteExecute = false;
|
|
220
220
|
if (model.optimization) {
|
|
221
|
-
if (model.slabSliceSpacingFraction === 1.0 && model.interpolator.isSeparable() && publicAPI.isPermutationMatrix(indexMatrix)) {
|
|
221
|
+
if (optimizedTransform == null && model.slabSliceSpacingFraction === 1.0 && model.interpolator.isSeparable() && publicAPI.isPermutationMatrix(indexMatrix)) {
|
|
222
222
|
model.usePermuteExecute = true;
|
|
223
223
|
if (publicAPI.canUseNearestNeighbor(indexMatrix, outWholeExt)) {
|
|
224
224
|
interpolationMode = InterpolationMode.NEAREST;
|
|
@@ -286,7 +286,7 @@ function vtkImageReslice(publicAPI, model) {
|
|
|
286
286
|
const rescaleScalars = model.scalarShift !== 0.0 || model.scalarScale !== 1.0;
|
|
287
287
|
|
|
288
288
|
// is nearest neighbor optimization possible?
|
|
289
|
-
const optimizeNearest = interpolationMode === InterpolationMode.NEAREST && borderMode === ImageBorderMode.CLAMP && !(perspective || convertScalars != null || rescaleScalars) && inputScalarType === outScalars.getDataType() && fullSize === inScalars.getNumberOfTuples() && model.border === true && nsamples <= 1;
|
|
289
|
+
const optimizeNearest = interpolationMode === InterpolationMode.NEAREST && borderMode === ImageBorderMode.CLAMP && !(optimizedTransform != null || perspective || convertScalars != null || rescaleScalars) && inputScalarType === outScalars.getDataType() && fullSize === inScalars.getNumberOfTuples() && model.border === true && nsamples <= 1;
|
|
290
290
|
|
|
291
291
|
// get pixel information
|
|
292
292
|
const scalarType = outScalars.getDataType();
|
|
@@ -306,11 +306,6 @@ function vtkImageReslice(publicAPI, model) {
|
|
|
306
306
|
origin[i] = newmat[4 * 3 + i];
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
// get the input origin and spacing for conversion purposes
|
|
310
|
-
model.interpolator.getOrigin();
|
|
311
|
-
const inSpacing = model.interpolator.getSpacing();
|
|
312
|
-
[1.0 / inSpacing[0], 1.0 / inSpacing[1], 1.0 / inSpacing[2]];
|
|
313
|
-
|
|
314
309
|
// allocate an output row of type double
|
|
315
310
|
let floatPtr = null;
|
|
316
311
|
if (!optimizeNearest) {
|
|
@@ -409,6 +404,16 @@ function vtkImageReslice(publicAPI, model) {
|
|
|
409
404
|
inPoint[1] *= f;
|
|
410
405
|
inPoint[2] *= f;
|
|
411
406
|
}
|
|
407
|
+
if (optimizedTransform !== null) {
|
|
408
|
+
// get the input origin and spacing for conversion purposes
|
|
409
|
+
const inOrigin = model.interpolator.getOrigin();
|
|
410
|
+
const inSpacing = model.interpolator.getSpacing();
|
|
411
|
+
const inInvSpacing = [1.0 / inSpacing[0], 1.0 / inSpacing[1], 1.0 / inSpacing[2]];
|
|
412
|
+
|
|
413
|
+
// apply the AbstractTransform if there is one
|
|
414
|
+
// TBD: handle inDirection
|
|
415
|
+
publicAPI.applyTransform(optimizedTransform, inPoint, inOrigin, inInvSpacing);
|
|
416
|
+
}
|
|
412
417
|
if (model.interpolator.checkBoundsIJK(inPoint)) {
|
|
413
418
|
// do the interpolation
|
|
414
419
|
isInBounds = 1;
|
|
@@ -541,63 +546,29 @@ function vtkImageReslice(publicAPI, model) {
|
|
|
541
546
|
* @returns
|
|
542
547
|
*/
|
|
543
548
|
publicAPI.getIndexMatrix = (input, output) => {
|
|
544
|
-
// first verify that we have to update the matrix
|
|
545
|
-
if (indexMatrix === null) {
|
|
546
|
-
indexMatrix = mat4.identity(new Float64Array(16));
|
|
547
|
-
}
|
|
548
|
-
const inOrigin = input.getOrigin();
|
|
549
|
-
const inSpacing = input.getSpacing();
|
|
550
|
-
const inDirection = input.getDirection();
|
|
551
|
-
const outOrigin = output.getOrigin();
|
|
552
|
-
const outSpacing = output.getSpacing();
|
|
553
549
|
const transform = mat4.identity(new Float64Array(16));
|
|
554
|
-
|
|
555
|
-
const outMatrix = mat4.identity(new Float64Array(16));
|
|
550
|
+
optimizedTransform = null;
|
|
556
551
|
if (model.resliceAxes) {
|
|
557
552
|
mat4.copy(transform, model.resliceAxes);
|
|
558
553
|
}
|
|
559
554
|
if (model.resliceTransform) {
|
|
560
555
|
if (model.resliceTransform.isA('vtkHomogeneousTransform')) {
|
|
561
|
-
// transform->PostMultiply();
|
|
562
|
-
// transform->Concatenate(
|
|
563
|
-
// mat4.multiply(transform, transform, model.resliceTransform.getMatrix());
|
|
564
556
|
mat4.multiply(transform, model.resliceTransform.getMatrix(), transform);
|
|
565
557
|
} else {
|
|
566
558
|
// TODO
|
|
567
559
|
vtkWarningMacro('Non homogeneous transform have not yet been ported');
|
|
568
560
|
}
|
|
569
561
|
}
|
|
570
|
-
if (!vtkMath.isIdentity3x3(inDirection)) {
|
|
571
|
-
const imageTransform = vtkMatrixBuilder.buildFromRadian().translate(inOrigin[0], inOrigin[1], inOrigin[2]).multiply3x3(inDirection).translate(-inOrigin[0], -inOrigin[1], -inOrigin[2]);
|
|
572
|
-
mat4.multiply(transform, imageTransform.getMatrix(), transform);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// check to see if we have an identity matrix
|
|
576
|
-
let isIdentity = vtkMath.isIdentity(transform);
|
|
577
562
|
|
|
578
563
|
// the outMatrix takes OutputData indices to OutputData coordinates,
|
|
564
|
+
const outMatrix = output.getIndexToWorld();
|
|
565
|
+
mat4.multiply(transform, transform, outMatrix);
|
|
566
|
+
|
|
579
567
|
// the inMatrix takes InputData coordinates to InputData indices
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
inMatrix[4 * i + i] = 1.0 / inSpacing[i];
|
|
585
|
-
inMatrix[4 * 3 + i] = -inOrigin[i] / inSpacing[i];
|
|
586
|
-
outMatrix[4 * i + i] = outSpacing[i];
|
|
587
|
-
outMatrix[4 * 3 + i] = outOrigin[i];
|
|
588
|
-
}
|
|
589
|
-
if (!isIdentity) {
|
|
590
|
-
// transform.PreMultiply();
|
|
591
|
-
// transform.Concatenate(outMatrix);
|
|
592
|
-
mat4.multiply(transform, transform, outMatrix);
|
|
593
|
-
|
|
594
|
-
// the optimizedTransform requires data coords, not
|
|
595
|
-
// index coords, as its input
|
|
596
|
-
{
|
|
597
|
-
// transform->PostMultiply();
|
|
598
|
-
// transform->Concatenate(inMatrix);
|
|
599
|
-
mat4.multiply(transform, inMatrix, transform);
|
|
600
|
-
}
|
|
568
|
+
// the optimizedTransform requires data coords, not index coords, as its input
|
|
569
|
+
if (optimizedTransform == null) {
|
|
570
|
+
const inMatrix = input.getWorldToIndex();
|
|
571
|
+
mat4.multiply(transform, inMatrix, transform);
|
|
601
572
|
}
|
|
602
573
|
mat4.copy(indexMatrix, transform);
|
|
603
574
|
return indexMatrix;
|
|
@@ -257,6 +257,9 @@ function vtkView2DProxy(publicAPI, model) {
|
|
|
257
257
|
}
|
|
258
258
|
publicAPI.bindRepresentationToManipulator = representation => {
|
|
259
259
|
let nbListeners = 0;
|
|
260
|
+
if (!representation.getProxyId) {
|
|
261
|
+
return nbListeners;
|
|
262
|
+
}
|
|
260
263
|
model.rangeManipulator.removeAllListeners();
|
|
261
264
|
model.sliceRepresentation = representation;
|
|
262
265
|
while (model.sliceRepresentationSubscriptions.length) {
|
|
@@ -38,7 +38,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
// Set the color of a volume to an RGB transfer function
|
|
41
|
-
publicAPI.setRGBTransferFunction = (
|
|
41
|
+
publicAPI.setRGBTransferFunction = function () {
|
|
42
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
43
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
42
44
|
// backwards compatible call without the component index
|
|
43
45
|
let idx = index;
|
|
44
46
|
let transferFunc = func;
|
|
@@ -61,7 +63,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
61
63
|
};
|
|
62
64
|
|
|
63
65
|
// Set the piecewise function
|
|
64
|
-
publicAPI.setPiecewiseFunction = (
|
|
66
|
+
publicAPI.setPiecewiseFunction = function () {
|
|
67
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
68
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
65
69
|
let idx = index;
|
|
66
70
|
let transferFunc = func;
|
|
67
71
|
if (!Number.isInteger(index)) {
|
|
@@ -83,7 +87,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
83
87
|
};
|
|
84
88
|
|
|
85
89
|
// Alias to set the piecewise function
|
|
86
|
-
publicAPI.setScalarOpacity = (
|
|
90
|
+
publicAPI.setScalarOpacity = function () {
|
|
91
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
92
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
87
93
|
// backwards compatible call without the component index
|
|
88
94
|
let idx = index;
|
|
89
95
|
let transferFunc = func;
|
|
@@ -99,7 +105,9 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
99
105
|
let idx = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
100
106
|
return publicAPI.getPiecewiseFunction(idx);
|
|
101
107
|
};
|
|
102
|
-
publicAPI.setComponentWeight = (
|
|
108
|
+
publicAPI.setComponentWeight = function () {
|
|
109
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
110
|
+
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
103
111
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
104
112
|
vtkErrorMacro('Invalid index');
|
|
105
113
|
return false;
|
|
@@ -112,7 +120,8 @@ function vtkImageProperty(publicAPI, model) {
|
|
|
112
120
|
}
|
|
113
121
|
return false;
|
|
114
122
|
};
|
|
115
|
-
publicAPI.getComponentWeight =
|
|
123
|
+
publicAPI.getComponentWeight = function () {
|
|
124
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
116
125
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
117
126
|
vtkErrorMacro('Invalid index');
|
|
118
127
|
return 0.0;
|
|
@@ -116,6 +116,16 @@ function vtkMapper2D(publicAPI, model) {
|
|
|
116
116
|
}
|
|
117
117
|
model.colorBuildString = `${publicAPI.getMTime()}${scalars.getMTime()}${alpha}`;
|
|
118
118
|
};
|
|
119
|
+
publicAPI.getPrimitiveCount = () => {
|
|
120
|
+
const input = publicAPI.getInputData();
|
|
121
|
+
const pcount = {
|
|
122
|
+
points: input.getPoints().getNumberOfValues() / 3,
|
|
123
|
+
verts: input.getVerts().getNumberOfValues() - input.getVerts().getNumberOfCells(),
|
|
124
|
+
lines: input.getLines().getNumberOfValues() - 2 * input.getLines().getNumberOfCells(),
|
|
125
|
+
triangles: input.getPolys().getNumberOfValues() - 3 * input.getPolys().getNumberOfCells()
|
|
126
|
+
};
|
|
127
|
+
return pcount;
|
|
128
|
+
};
|
|
119
129
|
}
|
|
120
130
|
|
|
121
131
|
// ----------------------------------------------------------------------------
|
|
@@ -94,22 +94,31 @@ function vtkRenderWindow(publicAPI, model) {
|
|
|
94
94
|
publicAPI.getStatistics = () => {
|
|
95
95
|
const results = {
|
|
96
96
|
propCount: 0,
|
|
97
|
-
invisiblePropCount: 0
|
|
97
|
+
invisiblePropCount: 0,
|
|
98
|
+
gpuMemoryMB: 0
|
|
98
99
|
};
|
|
100
|
+
model._views.forEach(v => {
|
|
101
|
+
results.gpuMemoryMB += v.getGraphicsMemoryInfo() / 1e6;
|
|
102
|
+
});
|
|
99
103
|
model.renderers.forEach(ren => {
|
|
100
104
|
const props = ren.getViewProps();
|
|
105
|
+
const gren = model._views[0].getViewNodeFor(ren);
|
|
101
106
|
props.forEach(prop => {
|
|
102
107
|
if (prop.getVisibility()) {
|
|
103
108
|
results.propCount += 1;
|
|
104
109
|
const mpr = prop.getMapper && prop.getMapper();
|
|
105
110
|
if (mpr && mpr.getPrimitiveCount) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const gmpr = gren.getViewNodeFor(mpr);
|
|
112
|
+
if (gmpr) {
|
|
113
|
+
results.gpuMemoryMB += gmpr.getAllocatedGPUMemoryInBytes() / 1e6;
|
|
114
|
+
const pcount = mpr.getPrimitiveCount();
|
|
115
|
+
Object.keys(pcount).forEach(keyName => {
|
|
116
|
+
if (!results[keyName]) {
|
|
117
|
+
results[keyName] = 0;
|
|
118
|
+
}
|
|
119
|
+
results[keyName] += pcount[keyName];
|
|
120
|
+
});
|
|
121
|
+
}
|
|
113
122
|
}
|
|
114
123
|
} else {
|
|
115
124
|
results.invisiblePropCount += 1;
|
|
@@ -63,7 +63,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
// Set the color of a volume to a gray transfer function
|
|
66
|
-
publicAPI.setGrayTransferFunction = (
|
|
66
|
+
publicAPI.setGrayTransferFunction = function () {
|
|
67
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
68
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
67
69
|
let modified = false;
|
|
68
70
|
if (model.componentData[index].grayTransferFunction !== func) {
|
|
69
71
|
model.componentData[index].grayTransferFunction = func;
|
|
@@ -80,7 +82,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
80
82
|
};
|
|
81
83
|
|
|
82
84
|
// Get the currently set gray transfer function. Create one if none set.
|
|
83
|
-
publicAPI.getGrayTransferFunction =
|
|
85
|
+
publicAPI.getGrayTransferFunction = function () {
|
|
86
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
84
87
|
if (model.componentData[index].grayTransferFunction === null) {
|
|
85
88
|
model.componentData[index].grayTransferFunction = vtkPiecewiseFunction.newInstance();
|
|
86
89
|
model.componentData[index].grayTransferFunction.addPoint(0, 0.0);
|
|
@@ -94,7 +97,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
94
97
|
};
|
|
95
98
|
|
|
96
99
|
// Set the color of a volume to an RGB transfer function
|
|
97
|
-
publicAPI.setRGBTransferFunction = (
|
|
100
|
+
publicAPI.setRGBTransferFunction = function () {
|
|
101
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
102
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
98
103
|
let modified = false;
|
|
99
104
|
if (model.componentData[index].rGBTransferFunction !== func) {
|
|
100
105
|
model.componentData[index].rGBTransferFunction = func;
|
|
@@ -111,7 +116,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
111
116
|
};
|
|
112
117
|
|
|
113
118
|
// Get the currently set RGB transfer function. Create one if none set.
|
|
114
|
-
publicAPI.getRGBTransferFunction =
|
|
119
|
+
publicAPI.getRGBTransferFunction = function () {
|
|
120
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
115
121
|
if (model.componentData[index].rGBTransferFunction === null) {
|
|
116
122
|
model.componentData[index].rGBTransferFunction = vtkColorTransferFunction.newInstance();
|
|
117
123
|
model.componentData[index].rGBTransferFunction.addRGBPoint(0, 0.0, 0.0, 0.0);
|
|
@@ -125,7 +131,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
125
131
|
};
|
|
126
132
|
|
|
127
133
|
// Set the scalar opacity of a volume to a transfer function
|
|
128
|
-
publicAPI.setScalarOpacity = (
|
|
134
|
+
publicAPI.setScalarOpacity = function () {
|
|
135
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
136
|
+
let func = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
129
137
|
if (model.componentData[index].scalarOpacity !== func) {
|
|
130
138
|
model.componentData[index].scalarOpacity = func;
|
|
131
139
|
publicAPI.modified();
|
|
@@ -135,7 +143,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
135
143
|
};
|
|
136
144
|
|
|
137
145
|
// Get the scalar opacity transfer function. Create one if none set.
|
|
138
|
-
publicAPI.getScalarOpacity =
|
|
146
|
+
publicAPI.getScalarOpacity = function () {
|
|
147
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
139
148
|
if (model.componentData[index].scalarOpacity === null) {
|
|
140
149
|
model.componentData[index].scalarOpacity = vtkPiecewiseFunction.newInstance();
|
|
141
150
|
model.componentData[index].scalarOpacity.addPoint(0, 1.0);
|
|
@@ -144,7 +153,9 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
144
153
|
}
|
|
145
154
|
return model.componentData[index].scalarOpacity;
|
|
146
155
|
};
|
|
147
|
-
publicAPI.setComponentWeight = (
|
|
156
|
+
publicAPI.setComponentWeight = function () {
|
|
157
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
158
|
+
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
148
159
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
149
160
|
vtkErrorMacro('Invalid index');
|
|
150
161
|
return false;
|
|
@@ -157,7 +168,8 @@ function vtkVolumeProperty(publicAPI, model) {
|
|
|
157
168
|
}
|
|
158
169
|
return false;
|
|
159
170
|
};
|
|
160
|
-
publicAPI.getComponentWeight =
|
|
171
|
+
publicAPI.getComponentWeight = function () {
|
|
172
|
+
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
161
173
|
if (index < 0 || index >= VTK_MAX_VRCOMP) {
|
|
162
174
|
vtkErrorMacro('Invalid index');
|
|
163
175
|
return 0.0;
|
|
@@ -70,6 +70,7 @@ function vtkOpenGLBufferObject(publicAPI, model) {
|
|
|
70
70
|
}
|
|
71
71
|
model.context.bindBuffer(convertType(internalType), internalHandle);
|
|
72
72
|
model.context.bufferData(convertType(internalType), data, model.context.STATIC_DRAW);
|
|
73
|
+
model.allocatedGPUMemoryInBytes = data.length * data.BYTES_PER_ELEMENT;
|
|
73
74
|
dirty = false;
|
|
74
75
|
return true;
|
|
75
76
|
};
|
|
@@ -92,6 +93,7 @@ function vtkOpenGLBufferObject(publicAPI, model) {
|
|
|
92
93
|
model.context.bindBuffer(convertType(internalType), null);
|
|
93
94
|
model.context.deleteBuffer(internalHandle);
|
|
94
95
|
internalHandle = null;
|
|
96
|
+
model.allocatedGPUMemoryInBytes = 0;
|
|
95
97
|
}
|
|
96
98
|
};
|
|
97
99
|
publicAPI.setOpenGLRenderWindow = rw => {
|
|
@@ -115,7 +117,8 @@ function vtkOpenGLBufferObject(publicAPI, model) {
|
|
|
115
117
|
const DEFAULT_VALUES = {
|
|
116
118
|
objectType: ObjectType.ARRAY_BUFFER,
|
|
117
119
|
// _openGLRenderWindow: null,
|
|
118
|
-
context: null
|
|
120
|
+
context: null,
|
|
121
|
+
allocatedGPUMemoryInBytes: 0
|
|
119
122
|
};
|
|
120
123
|
|
|
121
124
|
// ----------------------------------------------------------------------------
|
|
@@ -126,7 +129,7 @@ function extend(publicAPI, model) {
|
|
|
126
129
|
|
|
127
130
|
// Object methods
|
|
128
131
|
macro.obj(publicAPI, model);
|
|
129
|
-
macro.get(publicAPI, model, ['_openGLRenderWindow']);
|
|
132
|
+
macro.get(publicAPI, model, ['_openGLRenderWindow', 'allocatedGPUMemoryInBytes']);
|
|
130
133
|
macro.moveToProtected(publicAPI, model, ['openGLRenderWindow']);
|
|
131
134
|
vtkOpenGLBufferObject(publicAPI, model);
|
|
132
135
|
}
|
|
@@ -168,6 +168,7 @@ function vtkOpenGLHelper(publicAPI, model) {
|
|
|
168
168
|
}
|
|
169
169
|
return 6;
|
|
170
170
|
};
|
|
171
|
+
publicAPI.getAllocatedGPUMemoryInBytes = () => publicAPI.getCABO().getAllocatedGPUMemoryInBytes();
|
|
171
172
|
}
|
|
172
173
|
|
|
173
174
|
// ----------------------------------------------------------------------------
|
|
@@ -27,11 +27,10 @@ const {
|
|
|
27
27
|
// helper methods
|
|
28
28
|
// ----------------------------------------------------------------------------
|
|
29
29
|
|
|
30
|
-
function computeFnToString(property,
|
|
31
|
-
const pwfun = fn.apply(property);
|
|
30
|
+
function computeFnToString(property, pwfun, numberOfComponents) {
|
|
32
31
|
if (pwfun) {
|
|
33
32
|
const iComps = property.getIndependentComponents();
|
|
34
|
-
return `${
|
|
33
|
+
return `${pwfun.getMTime()}-${iComps}-${numberOfComponents}`;
|
|
35
34
|
}
|
|
36
35
|
return '0';
|
|
37
36
|
}
|
|
@@ -51,9 +50,6 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
51
50
|
model._openGLRenderWindow = model._openGLRenderer.getParent();
|
|
52
51
|
model.context = model._openGLRenderWindow.getContext();
|
|
53
52
|
model.tris.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
54
|
-
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
55
|
-
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
56
|
-
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
57
53
|
const ren = model._openGLRenderer.getRenderable();
|
|
58
54
|
model.openGLCamera = model._openGLRenderer.getViewNodeFor(ren.getActiveCamera());
|
|
59
55
|
// is slice set by the camera
|
|
@@ -226,7 +222,7 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
226
222
|
if (!model.currentRenderPass && model.lastRenderPassShaderReplacement || model.currentRenderPass && model.currentRenderPass.getShaderReplacement() !== model.lastRenderPassShaderReplacement) {
|
|
227
223
|
needRebuild = true;
|
|
228
224
|
}
|
|
229
|
-
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp) {
|
|
225
|
+
if (needRebuild || model.lastHaveSeenDepthRequest !== model.haveSeenDepthRequest || cellBO.getProgram()?.getHandle() === 0 || model.lastTextureComponents !== tNumComp || model.lastIndependentComponents !== iComp) {
|
|
230
226
|
model.lastHaveSeenDepthRequest = model.haveSeenDepthRequest;
|
|
231
227
|
model.lastTextureComponents = tNumComp;
|
|
232
228
|
model.lastIndependentComponents = iComp;
|
|
@@ -474,33 +470,34 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
474
470
|
const dataType = imgScalars.getDataType();
|
|
475
471
|
const numComp = imgScalars.getNumberOfComponents();
|
|
476
472
|
const actorProperty = actor.getProperty();
|
|
477
|
-
|
|
478
|
-
// set interpolation on the texture based on property setting
|
|
479
473
|
const iType = actorProperty.getInterpolationType();
|
|
480
|
-
if (iType === InterpolationType.NEAREST) {
|
|
481
|
-
model.colorTexture.setMinificationFilter(Filter.NEAREST);
|
|
482
|
-
model.colorTexture.setMagnificationFilter(Filter.NEAREST);
|
|
483
|
-
model.pwfTexture.setMinificationFilter(Filter.NEAREST);
|
|
484
|
-
model.pwfTexture.setMagnificationFilter(Filter.NEAREST);
|
|
485
|
-
} else {
|
|
486
|
-
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
487
|
-
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
488
|
-
model.pwfTexture.setMinificationFilter(Filter.LINEAR);
|
|
489
|
-
model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
|
|
490
|
-
}
|
|
491
474
|
const iComps = actorProperty.getIndependentComponents();
|
|
492
475
|
const numIComps = iComps ? numComp : 1;
|
|
493
476
|
const textureHeight = iComps ? 2 * numIComps : 1;
|
|
494
|
-
const
|
|
495
|
-
|
|
477
|
+
const colorTransferFunc = actorProperty.getRGBTransferFunction();
|
|
478
|
+
const cfunToString = computeFnToString(actorProperty, colorTransferFunc, numIComps);
|
|
479
|
+
const cTex = model._openGLRenderWindow.getGraphicsResourceForObject(colorTransferFunc);
|
|
480
|
+
const reBuildC = !cTex?.vtkObj || cTex?.hash !== cfunToString || model.colorTextureString !== cfunToString;
|
|
481
|
+
if (reBuildC) {
|
|
496
482
|
const cWidth = 1024;
|
|
497
483
|
const cSize = cWidth * textureHeight * 3;
|
|
498
484
|
const cTable = new Uint8Array(cSize);
|
|
499
|
-
|
|
500
|
-
|
|
485
|
+
if (!model.colorTexture) {
|
|
486
|
+
model.colorTexture = vtkOpenGLTexture.newInstance();
|
|
487
|
+
model.colorTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
488
|
+
}
|
|
489
|
+
// set interpolation on the texture based on property setting
|
|
490
|
+
if (iType === InterpolationType.NEAREST) {
|
|
491
|
+
model.colorTexture.setMinificationFilter(Filter.NEAREST);
|
|
492
|
+
model.colorTexture.setMagnificationFilter(Filter.NEAREST);
|
|
493
|
+
} else {
|
|
494
|
+
model.colorTexture.setMinificationFilter(Filter.LINEAR);
|
|
495
|
+
model.colorTexture.setMagnificationFilter(Filter.LINEAR);
|
|
496
|
+
}
|
|
497
|
+
if (colorTransferFunc) {
|
|
501
498
|
const tmpTable = new Float32Array(cWidth * 3);
|
|
502
499
|
for (let c = 0; c < numIComps; c++) {
|
|
503
|
-
cfun = actorProperty.getRGBTransferFunction(c);
|
|
500
|
+
const cfun = actorProperty.getRGBTransferFunction(c);
|
|
504
501
|
const cRange = cfun.getRange();
|
|
505
502
|
cfun.getTable(cRange[0], cRange[1], cWidth, tmpTable, 1);
|
|
506
503
|
if (iComps) {
|
|
@@ -514,6 +511,8 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
514
511
|
}
|
|
515
512
|
}
|
|
516
513
|
}
|
|
514
|
+
model.colorTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
515
|
+
model.colorTexture.resetFormatAndType();
|
|
517
516
|
model.colorTexture.create2DFromRaw(cWidth, textureHeight, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
518
517
|
} else {
|
|
519
518
|
for (let i = 0; i < cWidth * 3; ++i) {
|
|
@@ -524,24 +523,43 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
524
523
|
model.colorTexture.create2DFromRaw(cWidth, 1, 3, VtkDataTypes.UNSIGNED_CHAR, cTable);
|
|
525
524
|
}
|
|
526
525
|
model.colorTextureString = cfunToString;
|
|
526
|
+
if (colorTransferFunc) {
|
|
527
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(colorTransferFunc, model.colorTexture, model.colorTextureString);
|
|
528
|
+
}
|
|
529
|
+
} else {
|
|
530
|
+
model.colorTexture = cTex.vtkObj;
|
|
531
|
+
model.colorTextureString = cTex.hash;
|
|
527
532
|
}
|
|
528
533
|
|
|
529
534
|
// Build piecewise function buffer. This buffer is used either
|
|
530
535
|
// for component weighting or opacity, depending on whether we're
|
|
531
536
|
// rendering components independently or not.
|
|
532
|
-
const
|
|
533
|
-
|
|
537
|
+
const pwFunc = actorProperty.getPiecewiseFunction();
|
|
538
|
+
const pwfunToString = computeFnToString(actorProperty, pwFunc, numIComps);
|
|
539
|
+
const pwfTex = model._openGLRenderWindow.getGraphicsResourceForObject(pwFunc);
|
|
540
|
+
// rebuild opacity tfun?
|
|
541
|
+
const reBuildPwf = !pwfTex?.vtkObj || pwfTex?.hash !== pwfunToString || model.pwfTextureString !== pwfunToString;
|
|
542
|
+
if (reBuildPwf) {
|
|
534
543
|
const pwfWidth = 1024;
|
|
535
544
|
const pwfSize = pwfWidth * textureHeight;
|
|
536
545
|
const pwfTable = new Uint8Array(pwfSize);
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
546
|
+
if (!model.pwfTexture) {
|
|
547
|
+
model.pwfTexture = vtkOpenGLTexture.newInstance();
|
|
548
|
+
model.pwfTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
549
|
+
}
|
|
550
|
+
// set interpolation on the texture based on property setting
|
|
551
|
+
if (iType === InterpolationType.NEAREST) {
|
|
552
|
+
model.pwfTexture.setMinificationFilter(Filter.NEAREST);
|
|
553
|
+
model.pwfTexture.setMagnificationFilter(Filter.NEAREST);
|
|
554
|
+
} else {
|
|
555
|
+
model.pwfTexture.setMinificationFilter(Filter.LINEAR);
|
|
556
|
+
model.pwfTexture.setMagnificationFilter(Filter.LINEAR);
|
|
557
|
+
}
|
|
558
|
+
if (pwFunc) {
|
|
541
559
|
const pwfFloatTable = new Float32Array(pwfSize);
|
|
542
560
|
const tmpTable = new Float32Array(pwfWidth);
|
|
543
561
|
for (let c = 0; c < numIComps; ++c) {
|
|
544
|
-
pwfun = actorProperty.getPiecewiseFunction(c);
|
|
562
|
+
const pwfun = actorProperty.getPiecewiseFunction(c);
|
|
545
563
|
if (pwfun === null) {
|
|
546
564
|
// Piecewise constant max if no function supplied for this component
|
|
547
565
|
pwfFloatTable.fill(1.0);
|
|
@@ -561,6 +579,8 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
561
579
|
}
|
|
562
580
|
}
|
|
563
581
|
}
|
|
582
|
+
model.pwfTexture.releaseGraphicsResources(model._openGLRenderWindow);
|
|
583
|
+
model.pwfTexture.resetFormatAndType();
|
|
564
584
|
model.pwfTexture.create2DFromRaw(pwfWidth, textureHeight, 1, VtkDataTypes.FLOAT, pwfFloatTable);
|
|
565
585
|
} else {
|
|
566
586
|
// default is opaque
|
|
@@ -568,6 +588,12 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
568
588
|
model.pwfTexture.create2DFromRaw(pwfWidth, 1, 1, VtkDataTypes.UNSIGNED_CHAR, pwfTable);
|
|
569
589
|
}
|
|
570
590
|
model.pwfTextureString = pwfunToString;
|
|
591
|
+
if (pwFunc) {
|
|
592
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(pwFunc, model.pwfTexture, model.pwfTextureString);
|
|
593
|
+
}
|
|
594
|
+
} else {
|
|
595
|
+
model.pwfTexture = pwfTex.vtkObj;
|
|
596
|
+
model.pwfTextureString = pwfTex.hash;
|
|
571
597
|
}
|
|
572
598
|
|
|
573
599
|
// Find what IJK axis and what direction to slice along
|
|
@@ -605,6 +631,10 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
605
631
|
if (model.VBOBuildString !== toString) {
|
|
606
632
|
// Build the VBOs
|
|
607
633
|
const dims = image.getDimensions();
|
|
634
|
+
if (!model.openGLTexture) {
|
|
635
|
+
model.openGLTexture = vtkOpenGLTexture.newInstance();
|
|
636
|
+
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
637
|
+
}
|
|
608
638
|
if (iType === InterpolationType.NEAREST) {
|
|
609
639
|
if (new Set([1, 3, 4]).has(numComp) && dataType === VtkDataTypes.UNSIGNED_CHAR && !iComps) {
|
|
610
640
|
model.openGLTexture.setGenerateMipmap(true);
|
|
@@ -710,7 +740,19 @@ function vtkOpenGLImageMapper(publicAPI, model) {
|
|
|
710
740
|
} else {
|
|
711
741
|
vtkErrorMacro('Reformat slicing not yet supported.');
|
|
712
742
|
}
|
|
713
|
-
|
|
743
|
+
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
744
|
+
if (!tex?.vtkObj) {
|
|
745
|
+
if (model._scalars !== scalars) {
|
|
746
|
+
model._openGLRenderWindow.releaseGraphicsResourcesForObject(model._scalars);
|
|
747
|
+
model._scalars = scalars;
|
|
748
|
+
}
|
|
749
|
+
model.openGLTexture.resetFormatAndType();
|
|
750
|
+
model.openGLTexture.create2DFilterableFromRaw(dims[0], dims[1], numComp, imgScalars.getDataType(), scalars, model.renderable.getPreferSizeOverAccuracy?.());
|
|
751
|
+
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, model.VBOBuildString);
|
|
752
|
+
} else {
|
|
753
|
+
model.openGLTexture = tex.vtkObj;
|
|
754
|
+
model.VBOBuildString = tex.hash;
|
|
755
|
+
}
|
|
714
756
|
model.openGLTexture.activate();
|
|
715
757
|
model.openGLTexture.sendParameters();
|
|
716
758
|
model.openGLTexture.deactivate();
|
|
@@ -763,7 +805,8 @@ const DEFAULT_VALUES = {
|
|
|
763
805
|
pwfTexture: null,
|
|
764
806
|
lastHaveSeenDepthRequest: false,
|
|
765
807
|
haveSeenDepthRequest: false,
|
|
766
|
-
lastTextureComponents: 0
|
|
808
|
+
lastTextureComponents: 0,
|
|
809
|
+
_scalars: null
|
|
767
810
|
};
|
|
768
811
|
|
|
769
812
|
// ----------------------------------------------------------------------------
|
|
@@ -777,15 +820,6 @@ function extend(publicAPI, model) {
|
|
|
777
820
|
vtkReplacementShaderMapper.implementReplaceShaderCoincidentOffset(publicAPI, model, initialValues);
|
|
778
821
|
vtkReplacementShaderMapper.implementBuildShadersWithReplacements(publicAPI, model, initialValues);
|
|
779
822
|
model.tris = vtkHelper.newInstance();
|
|
780
|
-
model.openGLTexture = vtkOpenGLTexture.newInstance({
|
|
781
|
-
resizable: true
|
|
782
|
-
});
|
|
783
|
-
model.colorTexture = vtkOpenGLTexture.newInstance({
|
|
784
|
-
resizable: true
|
|
785
|
-
});
|
|
786
|
-
model.pwfTexture = vtkOpenGLTexture.newInstance({
|
|
787
|
-
resizable: true
|
|
788
|
-
});
|
|
789
823
|
model.imagemat = mat4.identity(new Float64Array(16));
|
|
790
824
|
model.imagematinv = mat4.identity(new Float64Array(16));
|
|
791
825
|
|