@kitware/vtk.js 32.11.0 → 32.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Rendering/Core/AbstractPicker.d.ts +13 -13
- package/Rendering/Core/AbstractPicker.js +1 -1
- 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/VolumeMapper.d.ts +34 -1
- package/Rendering/Core/VolumeMapper.js +7 -5
- package/Rendering/OpenGL/ImageCPRMapper.js +9 -0
- package/Rendering/OpenGL/ImageResliceMapper.js +14 -3
- package/Rendering/OpenGL/Texture.d.ts +19 -4
- package/Rendering/OpenGL/Texture.js +148 -21
- package/Rendering/OpenGL/VolumeMapper.js +11 -2
- package/package.json +11 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { vtkObject } from './../../interfaces';
|
|
2
2
|
import { Vector3 } from './../../types';
|
|
3
|
-
import
|
|
3
|
+
import vtkProp3D from './Prop3D';
|
|
4
4
|
import vtkRenderer from './Renderer';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -10,8 +10,8 @@ export interface IAbstractPickerInitialValues {
|
|
|
10
10
|
renderer?: vtkRenderer;
|
|
11
11
|
selectionPoint?: Vector3;
|
|
12
12
|
pickPosition?: Vector3;
|
|
13
|
-
pickFromList?:
|
|
14
|
-
pickList?:
|
|
13
|
+
pickFromList?: boolean;
|
|
14
|
+
pickList?: vtkProp3D[];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -20,15 +20,15 @@ export interface IAbstractPickerInitialValues {
|
|
|
20
20
|
export interface vtkAbstractPicker extends vtkObject {
|
|
21
21
|
/**
|
|
22
22
|
*
|
|
23
|
-
* @param {
|
|
23
|
+
* @param {vtkProp3D} prop
|
|
24
24
|
*/
|
|
25
|
-
addPickList(
|
|
25
|
+
addPickList(prop: vtkProp3D): void;
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
*
|
|
29
|
-
* @param {
|
|
29
|
+
* @param {vtkProp3D} prop
|
|
30
30
|
*/
|
|
31
|
-
deletePickList(
|
|
31
|
+
deletePickList(prop: vtkProp3D): void;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
*
|
|
@@ -38,7 +38,7 @@ export interface vtkAbstractPicker extends vtkObject {
|
|
|
38
38
|
/**
|
|
39
39
|
*
|
|
40
40
|
*/
|
|
41
|
-
getPickList():
|
|
41
|
+
getPickList(): vtkProp3D[];
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Get the picked position
|
|
@@ -82,17 +82,17 @@ export interface vtkAbstractPicker extends vtkObject {
|
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
84
|
*
|
|
85
|
-
* @param {
|
|
86
|
-
* @default
|
|
85
|
+
* @param {Boolean} pickFromList
|
|
86
|
+
* @default false
|
|
87
87
|
*/
|
|
88
|
-
setPickFromList(pickFromList:
|
|
88
|
+
setPickFromList(pickFromList: boolean): boolean;
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
91
|
*
|
|
92
|
-
* @param {
|
|
92
|
+
* @param {vtkProp3D[]} pickList
|
|
93
93
|
* @default []
|
|
94
94
|
*/
|
|
95
|
-
setPickList(pickList:
|
|
95
|
+
setPickList(pickList: vtkProp3D[]): boolean;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mat3, mat4, quat, vec3 } from 'gl-matrix';
|
|
2
|
-
import { Nullable } from './../../types';
|
|
2
|
+
import { Extent, Nullable } from './../../types';
|
|
3
3
|
import { vtkOutputPort } from './../../interfaces';
|
|
4
4
|
import vtkAbstractMapper3D, {
|
|
5
5
|
IAbstractMapper3DInitialValues,
|
|
@@ -307,6 +307,25 @@ export interface vtkImageCPRMapper
|
|
|
307
307
|
* @param imageData
|
|
308
308
|
*/
|
|
309
309
|
setImageConnection(imageData: vtkOutputPort): void;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Tells the mapper to only update the specified extents.
|
|
313
|
+
*
|
|
314
|
+
* If there are zero extents, the mapper updates the entire volume texture.
|
|
315
|
+
* Otherwise, the mapper will only update the texture by the specified extents
|
|
316
|
+
* during the next render call.
|
|
317
|
+
*
|
|
318
|
+
* This array is cleared after a successful render.
|
|
319
|
+
* @param extents
|
|
320
|
+
*/
|
|
321
|
+
setUpdatedExtents(extents: Extent[]): boolean;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Retrieves the updated extents.
|
|
325
|
+
*
|
|
326
|
+
* This array is cleared after every successful render.
|
|
327
|
+
*/
|
|
328
|
+
getUpdatedExtents(): Extent[];
|
|
310
329
|
}
|
|
311
330
|
|
|
312
331
|
/**
|
|
@@ -270,7 +270,7 @@ function vtkImageCPRMapper(publicAPI, model) {
|
|
|
270
270
|
// Object factory
|
|
271
271
|
// ----------------------------------------------------------------------------
|
|
272
272
|
|
|
273
|
-
const
|
|
273
|
+
const defaultValues = initialValues => ({
|
|
274
274
|
width: 10,
|
|
275
275
|
uniformOrientation: [0, 0, 0, 1],
|
|
276
276
|
useUniformOrientation: false,
|
|
@@ -282,14 +282,16 @@ const DEFAULT_VALUES = {
|
|
|
282
282
|
normalDirection: [0, 0, 1],
|
|
283
283
|
projectionSlabThickness: 1,
|
|
284
284
|
projectionSlabNumberOfSamples: 1,
|
|
285
|
-
projectionMode: ProjectionMode.MAX
|
|
286
|
-
|
|
285
|
+
projectionMode: ProjectionMode.MAX,
|
|
286
|
+
updatedExtents: [],
|
|
287
|
+
...initialValues
|
|
288
|
+
});
|
|
287
289
|
|
|
288
290
|
// ----------------------------------------------------------------------------
|
|
289
291
|
|
|
290
292
|
function extend(publicAPI, model) {
|
|
291
293
|
let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
292
|
-
Object.assign(model,
|
|
294
|
+
Object.assign(model, defaultValues(initialValues));
|
|
293
295
|
|
|
294
296
|
// Inheritance
|
|
295
297
|
vtkAbstractImageMapper.extend(publicAPI, model, initialValues);
|
|
@@ -302,7 +304,7 @@ function extend(publicAPI, model) {
|
|
|
302
304
|
});
|
|
303
305
|
|
|
304
306
|
// Setters and getters
|
|
305
|
-
macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'centerPoint', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection', 'projectionSlabThickness', 'projectionSlabNumberOfSamples', 'projectionMode']);
|
|
307
|
+
macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'centerPoint', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection', 'projectionSlabThickness', 'projectionSlabNumberOfSamples', 'projectionMode', 'updatedExtents']);
|
|
306
308
|
CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model);
|
|
307
309
|
|
|
308
310
|
// Object methods
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import vtkAbstractImageMapper, {
|
|
2
2
|
IAbstractImageMapperInitialValues,
|
|
3
3
|
} from './AbstractImageMapper';
|
|
4
|
-
import vtkImageData from './../../Common/DataModel/ImageData';
|
|
5
4
|
import vtkPlane from './../../Common/DataModel/Plane';
|
|
6
5
|
import vtkPolyData from './../../Common/DataModel/PolyData';
|
|
7
|
-
import { Bounds,
|
|
6
|
+
import { Bounds, Extent } from './../../types';
|
|
8
7
|
import { SlabTypes } from './ImageResliceMapper/Constants';
|
|
9
8
|
import CoincidentTopologyHelper, {
|
|
10
9
|
StaticCoincidentTopologyMethods,
|
|
@@ -116,6 +115,25 @@ export interface vtkImageResliceMapper
|
|
|
116
115
|
* @param {vtkPolyData} slicePolyData The polydata to slice the volume with. Default: null
|
|
117
116
|
*/
|
|
118
117
|
setSlicePolyData(slicePolyData: vtkPolyData): boolean;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Tells the mapper to only update the specified extents.
|
|
121
|
+
*
|
|
122
|
+
* If there are zero extents, the mapper updates the entire volume texture.
|
|
123
|
+
* Otherwise, the mapper will only update the texture by the specified extents
|
|
124
|
+
* during the next render call.
|
|
125
|
+
*
|
|
126
|
+
* This array is cleared after a successful render.
|
|
127
|
+
* @param extents
|
|
128
|
+
*/
|
|
129
|
+
setUpdatedExtents(extents: Extent[]): boolean;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Retrieves the updated extents.
|
|
133
|
+
*
|
|
134
|
+
* This array is cleared after every successful render.
|
|
135
|
+
*/
|
|
136
|
+
getUpdatedExtents(): Extent[];
|
|
119
137
|
}
|
|
120
138
|
|
|
121
139
|
/**
|
|
@@ -38,23 +38,25 @@ function vtkImageResliceMapper(publicAPI, model) {
|
|
|
38
38
|
// Object factory
|
|
39
39
|
// ----------------------------------------------------------------------------
|
|
40
40
|
|
|
41
|
-
const
|
|
41
|
+
const defaultValues = initialValues => ({
|
|
42
42
|
slabThickness: 0.0,
|
|
43
43
|
slabTrapezoidIntegration: 0,
|
|
44
44
|
slabType: SlabTypes.MEAN,
|
|
45
45
|
slicePlane: null,
|
|
46
|
-
slicePolyData: null
|
|
47
|
-
|
|
46
|
+
slicePolyData: null,
|
|
47
|
+
updatedExtents: [],
|
|
48
|
+
...initialValues
|
|
49
|
+
});
|
|
48
50
|
|
|
49
51
|
// ----------------------------------------------------------------------------
|
|
50
52
|
|
|
51
53
|
function extend(publicAPI, model) {
|
|
52
54
|
let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
53
|
-
Object.assign(model,
|
|
55
|
+
Object.assign(model, defaultValues(initialValues));
|
|
54
56
|
|
|
55
57
|
// Build VTK API
|
|
56
58
|
vtkAbstractImageMapper.extend(publicAPI, model, initialValues);
|
|
57
|
-
macro.setGet(publicAPI, model, ['slabThickness', 'slabTrapezoidIntegration', 'slabType', 'slicePlane', 'slicePolyData']);
|
|
59
|
+
macro.setGet(publicAPI, model, ['slabThickness', 'slabTrapezoidIntegration', 'slabType', 'slicePlane', 'slicePolyData', 'updatedExtents']);
|
|
58
60
|
CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model);
|
|
59
61
|
|
|
60
62
|
// Object methods
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import vtkPiecewiseFunction from './../../Common/DataModel/PiecewiseFunction';
|
|
2
|
-
import { Bounds, Range } from './../../types';
|
|
2
|
+
import { Bounds, Range, Extent } from './../../types';
|
|
3
3
|
import vtkAbstractMapper3D, {
|
|
4
4
|
IAbstractMapper3DInitialValues,
|
|
5
5
|
} from './AbstractMapper3D';
|
|
@@ -281,6 +281,39 @@ export interface vtkVolumeMapper extends vtkAbstractMapper3D {
|
|
|
281
281
|
*/
|
|
282
282
|
setLAOKernelRadius(LAOKernelRadius: number): void;
|
|
283
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Set kernel size for local ambient occlusion. It specifies the number of rays that are randomly sampled in the hemisphere.
|
|
286
|
+
* Value is clipped between 1 and 32.
|
|
287
|
+
* @param LAOKernelSize
|
|
288
|
+
*/
|
|
289
|
+
setLAOKernelSize(LAOKernelSize: number): void;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Set kernel radius for local ambient occlusion. It specifies the number of samples that are considered on each random ray.
|
|
293
|
+
* Value must be greater than or equal to 1.
|
|
294
|
+
* @param LAOKernelRadius
|
|
295
|
+
*/
|
|
296
|
+
setLAOKernelRadius(LAOKernelRadius: number): void;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Tells the mapper to only update the specified extents.
|
|
300
|
+
*
|
|
301
|
+
* If there are zero extents, the mapper updates the entire volume texture.
|
|
302
|
+
* Otherwise, the mapper will only update the texture by the specified extents
|
|
303
|
+
* during the next render call.
|
|
304
|
+
*
|
|
305
|
+
* This array is cleared after a successful render.
|
|
306
|
+
* @param extents
|
|
307
|
+
*/
|
|
308
|
+
setUpdatedExtents(extents: Extent[]): boolean;
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Retrieves the updated extents.
|
|
312
|
+
*
|
|
313
|
+
* This array is cleared after every successful render.
|
|
314
|
+
*/
|
|
315
|
+
getUpdatedExtents(): Extent[];
|
|
316
|
+
|
|
284
317
|
/**
|
|
285
318
|
*
|
|
286
319
|
*/
|
|
@@ -101,7 +101,7 @@ function vtkVolumeMapper(publicAPI, model) {
|
|
|
101
101
|
// ----------------------------------------------------------------------------
|
|
102
102
|
|
|
103
103
|
// TODO: what values to use for averageIPScalarRange to get GLSL to use max / min values like [-Math.inf, Math.inf]?
|
|
104
|
-
const
|
|
104
|
+
const defaultValues = initialValues => ({
|
|
105
105
|
bounds: [1, -1, 1, -1, 1, -1],
|
|
106
106
|
sampleDistance: 1.0,
|
|
107
107
|
imageSampleDistance: 1.0,
|
|
@@ -124,16 +124,18 @@ const DEFAULT_VALUES = {
|
|
|
124
124
|
// local ambient occlusion
|
|
125
125
|
localAmbientOcclusion: false,
|
|
126
126
|
LAOKernelSize: 15,
|
|
127
|
-
LAOKernelRadius: 7
|
|
128
|
-
|
|
127
|
+
LAOKernelRadius: 7,
|
|
128
|
+
updatedExtents: [],
|
|
129
|
+
...initialValues
|
|
130
|
+
});
|
|
129
131
|
|
|
130
132
|
// ----------------------------------------------------------------------------
|
|
131
133
|
|
|
132
134
|
function extend(publicAPI, model) {
|
|
133
135
|
let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
134
|
-
Object.assign(model,
|
|
136
|
+
Object.assign(model, defaultValues(initialValues));
|
|
135
137
|
vtkAbstractMapper3D.extend(publicAPI, model, initialValues);
|
|
136
|
-
macro.setGet(publicAPI, model, ['sampleDistance', 'imageSampleDistance', 'maximumSamplesPerRay', 'autoAdjustSampleDistances', 'initialInteractionScale', 'interactionSampleDistanceFactor', 'blendMode', 'filterMode', 'preferSizeOverAccuracy', 'computeNormalFromOpacity', 'volumetricScatteringBlending', 'globalIlluminationReach', 'volumeShadowSamplingDistFactor', 'anisotropy', 'localAmbientOcclusion', 'LAOKernelSize', 'LAOKernelRadius']);
|
|
138
|
+
macro.setGet(publicAPI, model, ['sampleDistance', 'imageSampleDistance', 'maximumSamplesPerRay', 'autoAdjustSampleDistances', 'initialInteractionScale', 'interactionSampleDistanceFactor', 'blendMode', 'filterMode', 'preferSizeOverAccuracy', 'computeNormalFromOpacity', 'volumetricScatteringBlending', 'globalIlluminationReach', 'volumeShadowSamplingDistFactor', 'anisotropy', 'localAmbientOcclusion', 'LAOKernelSize', 'LAOKernelRadius', 'updatedExtents']);
|
|
137
139
|
macro.setGetArray(publicAPI, model, ['ipScalarRange'], 2);
|
|
138
140
|
macro.event(publicAPI, model, 'lightingActivated');
|
|
139
141
|
|
|
@@ -156,6 +156,8 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
156
156
|
const cachedScalarsEntry = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
157
157
|
const volumeTextureHash = getImageDataHash(image, scalars);
|
|
158
158
|
const reBuildTex = !cachedScalarsEntry?.oglObject?.getHandle() || cachedScalarsEntry?.hash !== volumeTextureHash;
|
|
159
|
+
const updatedExtents = model.renderable.getUpdatedExtents();
|
|
160
|
+
const hasUpdatedExtents = !!updatedExtents.length;
|
|
159
161
|
if (reBuildTex) {
|
|
160
162
|
model.volumeTexture = vtkOpenGLTexture.newInstance();
|
|
161
163
|
model.volumeTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
@@ -174,6 +176,13 @@ function vtkOpenGLImageCPRMapper(publicAPI, model) {
|
|
|
174
176
|
} else {
|
|
175
177
|
model.volumeTexture = cachedScalarsEntry.oglObject;
|
|
176
178
|
}
|
|
179
|
+
if (hasUpdatedExtents) {
|
|
180
|
+
// If hasUpdatedExtents, then the texture is partially updated.
|
|
181
|
+
// clear the array to acknowledge the update.
|
|
182
|
+
model.renderable.setUpdatedExtents([]);
|
|
183
|
+
const dims = image.getDimensions();
|
|
184
|
+
model.volumeTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, false, updatedExtents);
|
|
185
|
+
}
|
|
177
186
|
|
|
178
187
|
// Rebuild the color texture if needed
|
|
179
188
|
const numComp = scalars.getNumberOfComponents();
|
|
@@ -185,15 +185,19 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
185
185
|
let toString = getImageDataHash(image, scalars);
|
|
186
186
|
const tex = model._openGLRenderWindow.getGraphicsResourceForObject(scalars);
|
|
187
187
|
const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== toString;
|
|
188
|
-
|
|
188
|
+
const updatedExtents = model.renderable.getUpdatedExtents();
|
|
189
|
+
const hasUpdatedExtents = !!updatedExtents.length;
|
|
190
|
+
if (reBuildTex && !hasUpdatedExtents) {
|
|
189
191
|
model.openGLTexture = vtkOpenGLTexture.newInstance();
|
|
190
192
|
model.openGLTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
191
193
|
// Build the image scalar texture
|
|
192
|
-
const dims = image.getDimensions();
|
|
193
194
|
// Use norm16 for the 3D texture if the extension is available
|
|
194
195
|
model.openGLTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
|
|
195
196
|
model.openGLTexture.resetFormatAndType();
|
|
196
|
-
|
|
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);
|
|
197
201
|
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.openGLTexture, toString);
|
|
198
202
|
if (scalars !== model._scalars) {
|
|
199
203
|
model._openGLRenderWindow.registerGraphicsResourceUser(scalars, publicAPI);
|
|
@@ -203,6 +207,13 @@ function vtkOpenGLImageResliceMapper(publicAPI, model) {
|
|
|
203
207
|
} else {
|
|
204
208
|
model.openGLTexture = tex.oglObject;
|
|
205
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
|
+
}
|
|
206
217
|
const ppty = actor.getProperty();
|
|
207
218
|
const iComps = ppty.getIndependentComponents();
|
|
208
219
|
const numIComps = iComps ? numComp : 1;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Wrap, Filter } from './Texture/Constants';
|
|
2
2
|
import vtkOpenGLRenderWindow from './RenderWindow';
|
|
3
|
-
import { Nullable } from './../../types';
|
|
3
|
+
import { Extent, Nullable } from './../../types';
|
|
4
4
|
import { VtkDataTypes } from './../../Common/Core/DataArray';
|
|
5
5
|
import { vtkViewNode } from './../SceneGraph/ViewNode';
|
|
6
6
|
import { vtkObject, vtkRange } from './../../interfaces';
|
|
@@ -275,12 +275,16 @@ export interface vtkOpenGLTexture extends vtkViewNode {
|
|
|
275
275
|
|
|
276
276
|
/**
|
|
277
277
|
* Creates a 3D texture from raw data.
|
|
278
|
+
*
|
|
279
|
+
* updatedExtents is currently incompatible with webgl1, since there's no extent scaling.
|
|
280
|
+
*
|
|
278
281
|
* @param width The width of the texture.
|
|
279
282
|
* @param height The height of the texture.
|
|
280
283
|
* @param depth The depth of the texture.
|
|
281
284
|
* @param numComps The number of components in the texture.
|
|
282
285
|
* @param dataType The data type of the texture.
|
|
283
286
|
* @param data The raw data for the texture.
|
|
287
|
+
* @param updatedExtents Only update the specified extents (default: [])
|
|
284
288
|
* @returns {boolean} True if the texture was successfully created, false otherwise.
|
|
285
289
|
*/
|
|
286
290
|
create3DFromRaw(
|
|
@@ -289,11 +293,15 @@ export interface vtkOpenGLTexture extends vtkViewNode {
|
|
|
289
293
|
depth: number,
|
|
290
294
|
numComps: number,
|
|
291
295
|
dataType: VtkDataTypes,
|
|
292
|
-
data: any
|
|
296
|
+
data: any,
|
|
297
|
+
updatedExtents?: Extent[]
|
|
293
298
|
): boolean;
|
|
294
299
|
|
|
295
300
|
/**
|
|
296
301
|
* Creates a 3D filterable texture from raw data, with a preference for size over accuracy if necessary.
|
|
302
|
+
*
|
|
303
|
+
* updatedExtents is currently incompatible with webgl1, since there's no extent scaling.
|
|
304
|
+
*
|
|
297
305
|
* @param width The width of the texture.
|
|
298
306
|
* @param height The height of the texture.
|
|
299
307
|
* @param depth The depth of the texture.
|
|
@@ -302,6 +310,7 @@ export interface vtkOpenGLTexture extends vtkViewNode {
|
|
|
302
310
|
* @param values The raw data for the texture.
|
|
303
311
|
* @param preferSizeOverAccuracy Whether to prefer texture size over accuracy.
|
|
304
312
|
* @param [ranges] The precomputed ranges of the data (optional). Provided to
|
|
313
|
+
* @param updatedExtents Only update the specified extents (default: [])
|
|
305
314
|
* prevent computation of the data ranges.
|
|
306
315
|
* @returns {boolean} True if the texture was successfully created, false
|
|
307
316
|
* otherwise.
|
|
@@ -314,16 +323,21 @@ export interface vtkOpenGLTexture extends vtkViewNode {
|
|
|
314
323
|
dataType: VtkDataTypes,
|
|
315
324
|
values: any,
|
|
316
325
|
preferSizeOverAccuracy: boolean,
|
|
317
|
-
ranges?: vtkRange[]
|
|
326
|
+
ranges?: vtkRange[],
|
|
327
|
+
updatedExtents?: Extent[]
|
|
318
328
|
): boolean;
|
|
319
329
|
|
|
320
330
|
/**
|
|
321
331
|
* Creates a 3D filterable texture from a data array, with a preference for size over accuracy if necessary.
|
|
332
|
+
*
|
|
333
|
+
* updatedExtents is currently incompatible with webgl1, since there's no extent scaling.
|
|
334
|
+
*
|
|
322
335
|
* @param width The width of the texture.
|
|
323
336
|
* @param height The height of the texture.
|
|
324
337
|
* @param depth The depth of the texture.
|
|
325
338
|
* @param dataArray The data array to use for the texture.
|
|
326
339
|
* @param preferSizeOverAccuracy Whether to prefer texture size over accuracy.
|
|
340
|
+
* @param updatedExtents Only update the specified extents (default: [])
|
|
327
341
|
* @returns {boolean} True if the texture was successfully created, false otherwise.
|
|
328
342
|
*/
|
|
329
343
|
create3DFilterableFromDataArray(
|
|
@@ -331,7 +345,8 @@ export interface vtkOpenGLTexture extends vtkViewNode {
|
|
|
331
345
|
height: number,
|
|
332
346
|
depth: number,
|
|
333
347
|
dataArray: any,
|
|
334
|
-
preferSizeOverAccuracy: boolean
|
|
348
|
+
preferSizeOverAccuracy: boolean,
|
|
349
|
+
updatedExtents?: Extent[]
|
|
335
350
|
): boolean;
|
|
336
351
|
|
|
337
352
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import DeepEqual from 'fast-deep-equal';
|
|
1
2
|
import Constants from './Texture/Constants.js';
|
|
2
3
|
import HalfFloat from '../../Common/Core/HalfFloat.js';
|
|
3
4
|
import { n as newInstance$1, o as obj, s as set, e as setGet, g as get, i as moveToProtected, a as newTypedArray, c as macro } from '../../macros2.js';
|
|
@@ -30,6 +31,16 @@ const {
|
|
|
30
31
|
function vtkOpenGLTexture(publicAPI, model) {
|
|
31
32
|
// Set our className
|
|
32
33
|
model.classHierarchy.push('vtkOpenGLTexture');
|
|
34
|
+
function getTexParams() {
|
|
35
|
+
return {
|
|
36
|
+
internalFormat: model.internalFormat,
|
|
37
|
+
format: model.format,
|
|
38
|
+
openGLDataType: model.openGLDataType,
|
|
39
|
+
width: model.width,
|
|
40
|
+
height: model.height
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
// Renders myself
|
|
34
45
|
publicAPI.render = function () {
|
|
35
46
|
let renWin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
@@ -148,6 +159,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
148
159
|
if (model.context && model.handle) {
|
|
149
160
|
model.context.deleteTexture(model.handle);
|
|
150
161
|
}
|
|
162
|
+
model._prevTexParams = null;
|
|
151
163
|
model.handle = 0;
|
|
152
164
|
model.numberOfDimensions = 0;
|
|
153
165
|
model.target = 0;
|
|
@@ -209,6 +221,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
209
221
|
rwin.activateTexture(publicAPI);
|
|
210
222
|
rwin.deactivateTexture(publicAPI);
|
|
211
223
|
model.context.deleteTexture(model.handle);
|
|
224
|
+
model._prevTexParams = null;
|
|
212
225
|
model.handle = 0;
|
|
213
226
|
model.numberOfDimensions = 0;
|
|
214
227
|
model.target = 0;
|
|
@@ -353,6 +366,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
353
366
|
|
|
354
367
|
//----------------------------------------------------------------------------
|
|
355
368
|
publicAPI.resetFormatAndType = () => {
|
|
369
|
+
model._prevTexParams = null;
|
|
356
370
|
model.format = 0;
|
|
357
371
|
model.internalFormat = 0;
|
|
358
372
|
model._forceInternalFormat = false;
|
|
@@ -499,6 +513,86 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
499
513
|
}
|
|
500
514
|
};
|
|
501
515
|
|
|
516
|
+
//----------------------------------------------------------------------------
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Gets the extent's size.
|
|
520
|
+
* @param {Extent} extent
|
|
521
|
+
*/
|
|
522
|
+
function getExtentSize(extent) {
|
|
523
|
+
const [xmin, xmax, ymin, ymax, zmin, zmax] = extent;
|
|
524
|
+
return [xmax - xmin + 1, ymax - ymin + 1, zmax - zmin + 1];
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
//----------------------------------------------------------------------------
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Gets the number of pixels in the extent.
|
|
531
|
+
* @param {Extent} extent
|
|
532
|
+
*/
|
|
533
|
+
function getExtentPixelCount(extent) {
|
|
534
|
+
const [sx, sy, sz] = getExtentSize(extent);
|
|
535
|
+
return sx * sy * sz;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
//----------------------------------------------------------------------------
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Reads a flattened extent from the image data and writes to the given output array.
|
|
542
|
+
*
|
|
543
|
+
* Assumes X varies the fastest and Z varies the slowest.
|
|
544
|
+
*
|
|
545
|
+
* @param {*} data
|
|
546
|
+
* @param {*} dataDims
|
|
547
|
+
* @param {Extent} extent
|
|
548
|
+
* @param {TypedArray} outArray
|
|
549
|
+
* @param {number} outOffset
|
|
550
|
+
* @returns
|
|
551
|
+
*/
|
|
552
|
+
function readExtentIntoArray(data, dataDims, extent, outArray, outOffset) {
|
|
553
|
+
const [xmin, xmax, ymin, ymax, zmin, zmax] = extent;
|
|
554
|
+
const [dx, dy] = dataDims;
|
|
555
|
+
const sxy = dx * dy;
|
|
556
|
+
let writeOffset = outOffset;
|
|
557
|
+
for (let zi = zmin; zi <= zmax; zi++) {
|
|
558
|
+
const zOffset = zi * sxy;
|
|
559
|
+
for (let yi = ymin; yi <= ymax; yi++) {
|
|
560
|
+
const zyOffset = zOffset + yi * dx;
|
|
561
|
+
// explicit alternative to data.subarray,
|
|
562
|
+
// due to potential perf issues on v8
|
|
563
|
+
for (let readOffset = zyOffset + xmin, end = zyOffset + xmax; readOffset <= end; readOffset++, writeOffset++) {
|
|
564
|
+
outArray[writeOffset] = data[readOffset];
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
//----------------------------------------------------------------------------
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Reads several image extents into a contiguous pixel array.
|
|
574
|
+
*
|
|
575
|
+
* @param {*} data
|
|
576
|
+
* @param {Extent[]} extent
|
|
577
|
+
* @param {TypedArrayConstructor} typedArrayConstructor optional typed array constructor
|
|
578
|
+
* @returns
|
|
579
|
+
*/
|
|
580
|
+
function readExtents(data, extents) {
|
|
581
|
+
let typedArrayConstructor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
582
|
+
const constructor = typedArrayConstructor || data.constructor;
|
|
583
|
+
const numPixels = extents.reduce((count, extent) => count + getExtentPixelCount(extent), 0);
|
|
584
|
+
const extentPixels = new constructor(numPixels);
|
|
585
|
+
const dataDims = [model.width, model.height, model.depth];
|
|
586
|
+
let writeOffset = 0;
|
|
587
|
+
extents.forEach(extent => {
|
|
588
|
+
readExtentIntoArray(data, dataDims, extent, extentPixels, writeOffset);
|
|
589
|
+
writeOffset += getExtentPixelCount(extent);
|
|
590
|
+
});
|
|
591
|
+
return extentPixels;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
//----------------------------------------------------------------------------
|
|
595
|
+
|
|
502
596
|
/**
|
|
503
597
|
* Updates the data array to match the required data type for OpenGL.
|
|
504
598
|
*
|
|
@@ -508,23 +602,30 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
508
602
|
* @param {string} dataType - The original data type of the input data.
|
|
509
603
|
* @param {Array} data - The input data array that needs to be updated.
|
|
510
604
|
* @param {boolean} [depth=false] - Indicates whether the data is a 3D array.
|
|
605
|
+
* @param {Array<Extent>} imageExtents only consider these image extents (default: [])
|
|
511
606
|
* @returns {Array} The updated data array that matches the OpenGL data type.
|
|
512
607
|
*/
|
|
513
608
|
publicAPI.updateArrayDataTypeForGL = function (dataType, data) {
|
|
514
609
|
let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
610
|
+
let imageExtents = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
515
611
|
const pixData = [];
|
|
516
612
|
let pixCount = model.width * model.height * model.components;
|
|
517
613
|
if (depth) {
|
|
518
614
|
pixCount *= model.depth;
|
|
519
615
|
}
|
|
616
|
+
const onlyUpdateExtents = !!imageExtents.length;
|
|
520
617
|
|
|
521
618
|
// if the opengl data type is float
|
|
522
619
|
// then the data array must be float
|
|
523
620
|
if (dataType !== VtkDataTypes.FLOAT && model.openGLDataType === model.context.FLOAT) {
|
|
524
621
|
for (let idx = 0; idx < data.length; idx++) {
|
|
525
622
|
if (data[idx]) {
|
|
526
|
-
|
|
527
|
-
|
|
623
|
+
if (onlyUpdateExtents) {
|
|
624
|
+
pixData.push(readExtents(data[idx], imageExtents, Float32Array));
|
|
625
|
+
} else {
|
|
626
|
+
const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
|
|
627
|
+
pixData.push(new Float32Array(dataArrayToCopy));
|
|
628
|
+
}
|
|
528
629
|
} else {
|
|
529
630
|
pixData.push(null);
|
|
530
631
|
}
|
|
@@ -536,8 +637,12 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
536
637
|
if (dataType !== VtkDataTypes.UNSIGNED_CHAR && model.openGLDataType === model.context.UNSIGNED_BYTE) {
|
|
537
638
|
for (let idx = 0; idx < data.length; idx++) {
|
|
538
639
|
if (data[idx]) {
|
|
539
|
-
|
|
540
|
-
|
|
640
|
+
if (onlyUpdateExtents) {
|
|
641
|
+
pixData.push(readExtents(data[idx], imageExtents, Uint8Array));
|
|
642
|
+
} else {
|
|
643
|
+
const dataArrayToCopy = data[idx].length > pixCount ? data[idx].subarray(0, pixCount) : data[idx];
|
|
644
|
+
pixData.push(new Uint8Array(dataArrayToCopy));
|
|
645
|
+
}
|
|
541
646
|
} else {
|
|
542
647
|
pixData.push(null);
|
|
543
648
|
}
|
|
@@ -556,9 +661,10 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
556
661
|
if (halfFloat) {
|
|
557
662
|
for (let idx = 0; idx < data.length; idx++) {
|
|
558
663
|
if (data[idx]) {
|
|
559
|
-
const
|
|
560
|
-
const
|
|
561
|
-
|
|
664
|
+
const src = onlyUpdateExtents ? readExtents(data[idx], imageExtents) : data[idx];
|
|
665
|
+
const newArray = new Uint16Array(onlyUpdateExtents ? src.length : pixCount);
|
|
666
|
+
const newArrayLen = newArray.length;
|
|
667
|
+
for (let i = 0; i < newArrayLen; i++) {
|
|
562
668
|
newArray[i] = toHalf(src[i]);
|
|
563
669
|
}
|
|
564
670
|
pixData.push(newArray);
|
|
@@ -571,7 +677,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
571
677
|
// The output has to be filled
|
|
572
678
|
if (pixData.length === 0) {
|
|
573
679
|
for (let i = 0; i < data.length; i++) {
|
|
574
|
-
pixData.push(data[i]);
|
|
680
|
+
pixData.push(onlyUpdateExtents && data[i] ? readExtents(data[i], imageExtents) : data[i]);
|
|
575
681
|
}
|
|
576
682
|
}
|
|
577
683
|
return pixData;
|
|
@@ -1056,7 +1162,8 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1056
1162
|
};
|
|
1057
1163
|
|
|
1058
1164
|
//----------------------------------------------------------------------------
|
|
1059
|
-
publicAPI.create3DFromRaw = (width, height, depth, numComps, dataType, data)
|
|
1165
|
+
publicAPI.create3DFromRaw = function (width, height, depth, numComps, dataType, data) {
|
|
1166
|
+
let updatedExtents = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : [];
|
|
1060
1167
|
let dataTypeToUse = dataType;
|
|
1061
1168
|
let dataToUse = data;
|
|
1062
1169
|
if (!publicAPI.updateVolumeInfoForGL(dataTypeToUse, numComps) && dataToUse) {
|
|
@@ -1098,25 +1205,42 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1098
1205
|
model._openGLRenderWindow.activateTexture(publicAPI);
|
|
1099
1206
|
publicAPI.createTexture();
|
|
1100
1207
|
publicAPI.bind();
|
|
1208
|
+
const hasUpdatedExtents = updatedExtents.length > 0;
|
|
1209
|
+
|
|
1210
|
+
// It's possible for the texture parameters to change while
|
|
1211
|
+
// streaming, so check for such a change.
|
|
1212
|
+
const rebuildEntireTexture = !hasUpdatedExtents || !DeepEqual(model._prevTexParams, getTexParams());
|
|
1213
|
+
|
|
1101
1214
|
// Create an array of texture with one texture
|
|
1102
1215
|
const dataArray = [dataToUse];
|
|
1103
1216
|
const is3DArray = true;
|
|
1104
|
-
const pixData = publicAPI.updateArrayDataTypeForGL(dataTypeToUse, dataArray, is3DArray);
|
|
1217
|
+
const pixData = publicAPI.updateArrayDataTypeForGL(dataTypeToUse, dataArray, is3DArray, rebuildEntireTexture ? [] : updatedExtents);
|
|
1105
1218
|
const scaledData = scaleTextureToHighestPowerOfTwo(pixData);
|
|
1106
1219
|
|
|
1107
1220
|
// Source texture data from the PBO.
|
|
1108
1221
|
// model.context.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
1109
1222
|
model.context.pixelStorei(model.context.UNPACK_ALIGNMENT, 1);
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1223
|
+
if (rebuildEntireTexture) {
|
|
1224
|
+
if (useTexStorage(dataTypeToUse)) {
|
|
1225
|
+
model.context.texStorage3D(model.target, 1, model.internalFormat, model.width, model.height, model.depth);
|
|
1226
|
+
if (scaledData[0] != null) {
|
|
1227
|
+
model.context.texSubImage3D(model.target, 0, 0, 0, 0, model.width, model.height, model.depth, model.format, model.openGLDataType, scaledData[0]);
|
|
1228
|
+
}
|
|
1229
|
+
} else {
|
|
1230
|
+
model.context.texImage3D(model.target, 0, model.internalFormat, model.width, model.height, model.depth, 0, model.format, model.openGLDataType, scaledData[0]);
|
|
1231
|
+
}
|
|
1232
|
+
model._prevTexParams = getTexParams();
|
|
1233
|
+
} else if (hasUpdatedExtents) {
|
|
1234
|
+
const extentPixels = scaledData[0];
|
|
1235
|
+
let readOffset = 0;
|
|
1236
|
+
for (let i = 0; i < updatedExtents.length; i++) {
|
|
1237
|
+
const extent = updatedExtents[i];
|
|
1238
|
+
const extentSize = getExtentSize(extent);
|
|
1239
|
+
const extentPixelCount = getExtentPixelCount(extent);
|
|
1240
|
+
const textureData = new extentPixels.constructor(extentPixels.buffer, readOffset, extentPixelCount);
|
|
1241
|
+
readOffset += textureData.byteLength;
|
|
1242
|
+
model.context.texSubImage3D(model.target, 0, extent[0], extent[2], extent[4], extentSize[0], extentSize[1], extentSize[2], model.format, model.openGLDataType, textureData);
|
|
1117
1243
|
}
|
|
1118
|
-
} else {
|
|
1119
|
-
model.context.texImage3D(model.target, 0, model.internalFormat, model.width, model.height, model.depth, 0, model.format, model.openGLDataType, scaledData[0]);
|
|
1120
1244
|
}
|
|
1121
1245
|
if (model.generateMipmap) {
|
|
1122
1246
|
model.context.generateMipmap(model.target);
|
|
@@ -1132,18 +1256,20 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1132
1256
|
publicAPI.create3DFilterableFromRaw = function (width, height, depth, numberOfComponents, dataType, values) {
|
|
1133
1257
|
let preferSizeOverAccuracy = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
|
|
1134
1258
|
let ranges = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : undefined;
|
|
1259
|
+
let updatedExtents = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : [];
|
|
1135
1260
|
return publicAPI.create3DFilterableFromDataArray(width, height, depth, vtkDataArray.newInstance({
|
|
1136
1261
|
numberOfComponents,
|
|
1137
1262
|
dataType,
|
|
1138
1263
|
values,
|
|
1139
1264
|
ranges
|
|
1140
|
-
}), preferSizeOverAccuracy);
|
|
1265
|
+
}), preferSizeOverAccuracy, updatedExtents);
|
|
1141
1266
|
};
|
|
1142
1267
|
|
|
1143
1268
|
//----------------------------------------------------------------------------
|
|
1144
1269
|
// This method create a 3D texture from dimensions and a DataArray
|
|
1145
1270
|
publicAPI.create3DFilterableFromDataArray = function (width, height, depth, dataArray) {
|
|
1146
1271
|
let preferSizeOverAccuracy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
1272
|
+
let updatedExtents = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : [];
|
|
1147
1273
|
const {
|
|
1148
1274
|
numComps,
|
|
1149
1275
|
dataType,
|
|
@@ -1178,7 +1304,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1178
1304
|
|
|
1179
1305
|
// WebGL2 path, we have 3d textures etc
|
|
1180
1306
|
if (model._openGLRenderWindow.getWebgl2()) {
|
|
1181
|
-
return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data);
|
|
1307
|
+
return publicAPI.create3DFromRaw(width, height, depth, numComps, dataType, data, updatedExtents);
|
|
1182
1308
|
}
|
|
1183
1309
|
const numPixelsIn = width * height * depth;
|
|
1184
1310
|
const scaleOffsetsCopy = structuredClone(scaleOffsets);
|
|
@@ -1347,6 +1473,7 @@ function vtkOpenGLTexture(publicAPI, model) {
|
|
|
1347
1473
|
const DEFAULT_VALUES = {
|
|
1348
1474
|
_openGLRenderWindow: null,
|
|
1349
1475
|
_forceInternalFormat: false,
|
|
1476
|
+
_prevTexParams: null,
|
|
1350
1477
|
context: null,
|
|
1351
1478
|
handle: 0,
|
|
1352
1479
|
sendParametersTime: null,
|
|
@@ -1138,7 +1138,9 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1138
1138
|
// rebuild the scalarTexture if the data has changed
|
|
1139
1139
|
toString = getImageDataHash(image, scalars);
|
|
1140
1140
|
const reBuildTex = !tex?.oglObject?.getHandle() || tex?.hash !== toString;
|
|
1141
|
-
|
|
1141
|
+
const updatedExtents = model.renderable.getUpdatedExtents();
|
|
1142
|
+
const hasUpdatedExtents = !!updatedExtents.length;
|
|
1143
|
+
if (reBuildTex && !hasUpdatedExtents) {
|
|
1142
1144
|
model.scalarTexture = vtkOpenGLTexture.newInstance();
|
|
1143
1145
|
model.scalarTexture.setOpenGLRenderWindow(model._openGLRenderWindow);
|
|
1144
1146
|
// Build the textures
|
|
@@ -1146,7 +1148,7 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1146
1148
|
// Use norm16 for scalar texture if the extension is available
|
|
1147
1149
|
model.scalarTexture.setOglNorm16Ext(model.context.getExtension('EXT_texture_norm16'));
|
|
1148
1150
|
model.scalarTexture.resetFormatAndType();
|
|
1149
|
-
model.scalarTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars
|
|
1151
|
+
model.scalarTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars);
|
|
1150
1152
|
if (scalars) {
|
|
1151
1153
|
model._openGLRenderWindow.setGraphicsResourceForObject(scalars, model.scalarTexture, toString);
|
|
1152
1154
|
if (scalars !== model._scalars) {
|
|
@@ -1158,6 +1160,13 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
|
|
|
1158
1160
|
} else {
|
|
1159
1161
|
model.scalarTexture = tex.oglObject;
|
|
1160
1162
|
}
|
|
1163
|
+
if (hasUpdatedExtents) {
|
|
1164
|
+
// If hasUpdatedExtents, then the texture is partially updated.
|
|
1165
|
+
// clear the array to acknowledge the update.
|
|
1166
|
+
model.renderable.setUpdatedExtents([]);
|
|
1167
|
+
const dims = image.getDimensions();
|
|
1168
|
+
model.scalarTexture.create3DFilterableFromDataArray(dims[0], dims[1], dims[2], scalars, false, updatedExtents);
|
|
1169
|
+
}
|
|
1161
1170
|
if (!model.tris.getCABO().getElementCount()) {
|
|
1162
1171
|
// build the CABO
|
|
1163
1172
|
const ptsArray = new Float32Array(12);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitware/vtk.js",
|
|
3
|
-
"version": "32.
|
|
3
|
+
"version": "32.12.1",
|
|
4
4
|
"description": "Visualization Toolkit for the Web",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"3d",
|
|
@@ -141,19 +141,20 @@
|
|
|
141
141
|
"reformat-only": "prettier --single-quote --trailing-comma es5 --print-width 80 --arrow-parens always --write",
|
|
142
142
|
"lint-fix": "eslint --fix Sources Examples",
|
|
143
143
|
"lint": "eslint Sources Examples",
|
|
144
|
-
"doc": "kw-doc -c ./Documentation/config.js",
|
|
145
|
-
"doc:www": "npm t -- --single-run && kw-doc -c ./Documentation/config.js -s",
|
|
146
|
-
"doc:minified": "kw-doc -c ./Documentation/config.js -m",
|
|
147
|
-
"doc:generate-api": "node ./Documentation/generate-api-docs.js",
|
|
144
|
+
"doc": "npm run build:pre && kw-doc -c ./Documentation/config.js",
|
|
145
|
+
"doc:www": "npm t -- --single-run && npm run build:pre && kw-doc -c ./Documentation/config.js -s",
|
|
146
|
+
"doc:minified": "npm run build:pre && kw-doc -c ./Documentation/config.js -m",
|
|
147
|
+
"doc:generate-api": "npm run build:pre && node ./Documentation/generate-api-docs.js",
|
|
148
148
|
"example": "node ./Utilities/ExampleRunner/example-runner-cli.js -c ./Documentation/config.js",
|
|
149
149
|
"example:https": "node ./Utilities/ExampleRunner/example-runner-cli.js --server-type https -c ./Documentation/config.js",
|
|
150
150
|
"example:webgpu": "cross-env WEBGPU=1 NO_WEBGL=1 node ./Utilities/ExampleRunner/example-runner-cli.js --server-type https -c ./Documentation/config.js",
|
|
151
|
+
"build:pre": "patch-package",
|
|
151
152
|
"dev:esm": "npm run build:esm -- -w",
|
|
152
|
-
"dev:umd": "webpack --watch --config webpack.dev.js --progress",
|
|
153
|
+
"dev:umd": "npm run build:pre && webpack --watch --config webpack.dev.js --progress",
|
|
153
154
|
"build": "npm run build:release",
|
|
154
|
-
"build:esm": "rollup -c rollup.config.js",
|
|
155
|
-
"build:umd": "webpack --config webpack.prod.js --progress",
|
|
156
|
-
"build:release": "npm run lint && concurrently \"cross-env NOLINT=1 npm run build:esm\" \"cross-env NOLINT=1 npm run build:umd\"",
|
|
155
|
+
"build:esm": "npm run build:pre && rollup -c rollup.config.js",
|
|
156
|
+
"build:umd": "npm run build:pre && webpack --config webpack.prod.js --progress",
|
|
157
|
+
"build:release": "npm run lint && npm run build:pre && concurrently \"cross-env NOLINT=1 npm run build:esm\" \"cross-env NOLINT=1 npm run build:umd\"",
|
|
157
158
|
"release:create-packages": "node ./Utilities/ci/build-npm-package.js",
|
|
158
159
|
"test": "karma start ./karma.conf.js",
|
|
159
160
|
"test:headless": "karma start ./karma.conf.js --browsers ChromeHeadlessNoSandbox --single-run",
|
|
@@ -163,8 +164,7 @@
|
|
|
163
164
|
"test:firefox-debug": "karma start ./karma.conf.js --browsers Firefox --no-single-run",
|
|
164
165
|
"commit": "git cz",
|
|
165
166
|
"semantic-release": "semantic-release",
|
|
166
|
-
"prepare": "node ./Utilities/prepare.js"
|
|
167
|
-
"postinstall": "patch-package"
|
|
167
|
+
"prepare": "node ./Utilities/prepare.js"
|
|
168
168
|
},
|
|
169
169
|
"config": {
|
|
170
170
|
"commitizen": {
|