@kitware/vtk.js 33.3.2 → 34.0.0-beta.2

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.
Files changed (56) hide show
  1. package/BREAKING_CHANGES.md +10 -0
  2. package/IO/Geometry/GLTFImporter/Decoder.js +21 -35
  3. package/IO/Geometry/GLTFImporter/ORMTexture.worker.js +42 -0
  4. package/IO/Geometry/GLTFImporter/Parser.js +6 -15
  5. package/IO/Geometry/GLTFImporter/Reader.js +10 -7
  6. package/IO/Geometry/GLTFImporter/Utils.js +27 -9
  7. package/Interaction/Manipulators/KeyboardCameraManipulator.d.ts +113 -0
  8. package/Rendering/Core/Actor.d.ts +5 -20
  9. package/Rendering/Core/Actor.js +5 -68
  10. package/Rendering/Core/ImageCPRMapper.d.ts +1 -20
  11. package/Rendering/Core/ImageCPRMapper.js +1 -2
  12. package/Rendering/Core/ImageProperty.d.ts +20 -1
  13. package/Rendering/Core/ImageProperty.js +7 -5
  14. package/Rendering/Core/ImageResliceMapper.d.ts +1 -20
  15. package/Rendering/Core/ImageResliceMapper.js +1 -2
  16. package/Rendering/Core/ImageSlice.d.ts +7 -23
  17. package/Rendering/Core/ImageSlice.js +9 -68
  18. package/Rendering/Core/Prop3D.d.ts +39 -2
  19. package/Rendering/Core/Prop3D.js +81 -2
  20. package/Rendering/Core/RenderWindowInteractor.d.ts +6 -0
  21. package/Rendering/Core/RenderWindowInteractor.js +7 -5
  22. package/Rendering/Core/Volume.d.ts +5 -20
  23. package/Rendering/Core/Volume.js +2 -70
  24. package/Rendering/Core/VolumeMapper/Constants.d.ts +0 -7
  25. package/Rendering/Core/VolumeMapper/Constants.js +2 -8
  26. package/Rendering/Core/VolumeMapper.d.ts +16 -173
  27. package/Rendering/Core/VolumeMapper.js +16 -51
  28. package/Rendering/Core/VolumeProperty/Constants.d.ts +12 -3
  29. package/Rendering/Core/VolumeProperty/Constants.js +11 -4
  30. package/Rendering/Core/VolumeProperty.d.ts +140 -5
  31. package/Rendering/Core/VolumeProperty.js +54 -7
  32. package/Rendering/OpenGL/Framebuffer.js +7 -1
  33. package/Rendering/OpenGL/ImageCPRMapper.js +72 -27
  34. package/Rendering/OpenGL/ImageMapper.js +71 -33
  35. package/Rendering/OpenGL/ImageResliceMapper.js +306 -183
  36. package/Rendering/OpenGL/OrderIndependentTranslucentPass.js +20 -3
  37. package/Rendering/OpenGL/PolyDataMapper.js +8 -9
  38. package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.d.ts +3 -3
  39. package/Rendering/OpenGL/RenderWindow/resourceSharingHelper.js +8 -5
  40. package/Rendering/OpenGL/SurfaceLIC/LineIntegralConvolution2D/pingpong.js +7 -1
  41. package/Rendering/OpenGL/SurfaceLIC/SurfaceLICInterface.js +20 -3
  42. package/Rendering/OpenGL/Texture.d.ts +110 -62
  43. package/Rendering/OpenGL/Texture.js +145 -37
  44. package/Rendering/OpenGL/VolumeMapper.js +763 -783
  45. package/Rendering/OpenGL/glsl/vtkVolumeFS.glsl.js +1 -1
  46. package/Rendering/WebGPU/CellArrayMapper.js +17 -17
  47. package/Rendering/WebGPU/PolyDataMapper.js +15 -35
  48. package/Rendering/WebGPU/Renderer.js +1 -1
  49. package/Rendering/WebGPU/Texture.js +12 -13
  50. package/Rendering/WebGPU/TextureManager.js +7 -12
  51. package/Rendering/WebGPU/VolumePassFSQ.js +2 -2
  52. package/_virtual/rollup-plugin-worker-loader__module_Sources/IO/Geometry/GLTFImporter/ORMTexture.worker.js +296 -0
  53. package/index.d.ts +1 -0
  54. package/macros.js +1 -1
  55. package/macros2.js +8 -3
  56. package/package.json +1 -1
@@ -1,3 +1,13 @@
1
+ ## From 33.x to 34
2
+
3
+ - **vtkMapper**: many properties have moved to `vtkVolumeProperty`. The full list of changed methods is: `getAnisotropy`, `getComputeNormalFromOpacity`, `getFilterMode`, `getFilterModeAsString`, `getGlobalIlluminationReach`, `getIpScalarRange`, `getIpScalarRangeByReference`, `getLAOKernelRadius`, `getLAOKernelSize`, `getLocalAmbientOcclusion`, `getPreferSizeOverAccuracy`, `getVolumetricScatteringBlending`, `setAnisotropy`, `setAverageIPScalarRange`, `setComputeNormalFromOpacity`, `setFilterMode`, `setFilterModeToNormalized`, `setFilterModeToOff`, `setFilterModeToRaw`, `setGlobalIlluminationReach`, `setIpScalarRange`, `setIpScalarRangeFrom`, `setLAOKernelRadius`, `setLAOKernelSize`, `setLocalAmbientOcclusion`, `setPreferSizeOverAccuracy`, `setVolumetricScatteringBlending`.
4
+ - **vtkRenderWindowInteractor**: KeyPress, KeyDown and KeyUp events are now observed on the container and no longer on the document. "tabIndex=0" is now automatically added on RWI containers to give focus on your render windows and catch key events. Check the KeyPressEvents example for usage.
5
+ - **vtkOpenGLTexture**: The public `create2D*` and `create3D*` methods used to have positional parameters. These methods now use named parameters via passing in an object record.
6
+
7
+ ## From 32.x to 33
8
+
9
+ - **vtkColorTransferFunction**, **vtkMapper**: Previous log scaling was disabled but functionality is now quite different from what it maybe was before it was disabled. ColorTransfer function now maps the model.nodes in logarithmic scales so there's an even spacing between powers of ten.
10
+
1
11
  ## From 31.x to 32
2
12
 
3
13
  - **vtkMapper**: remove `mapScalarsToTexture` from the public API. The function becomes protected and its API changes. This shouldn't cause any issue in most cases.
@@ -1,79 +1,65 @@
1
1
  import BinaryHelper from '../../Core/BinaryHelper.js';
2
- import { BINARY_HEADER_LENGTH, BINARY_HEADER_MAGIC, BINARY_CHUNK_TYPES, BINARY_CHUNK_HEADER_INTS, BINARY_HEADER_INTS } from './Constants.js';
2
+ import { BINARY_HEADER_MAGIC, BINARY_CHUNK_TYPES, BINARY_CHUNK_HEADER_INTS, BINARY_HEADER_LENGTH, BINARY_HEADER_INTS } from './Constants.js';
3
3
 
4
4
  function getChunkInfo(headerStart, data) {
5
- // Cache array view
6
5
  const header = new Uint32Array(data, headerStart, BINARY_CHUNK_HEADER_INTS);
7
6
  const chunkStart = headerStart + BINARY_CHUNK_HEADER_INTS * 4;
7
+ const chunkLength = header[0];
8
+ const chunkType = header[1];
8
9
  return {
9
10
  start: chunkStart,
10
- length: header[0],
11
- type: header[1]
11
+ length: chunkLength,
12
+ type: chunkType
12
13
  };
13
14
  }
14
15
  function getAllChunkInfos(data) {
15
- // Pre-calculate array size
16
- const maxChunks = Math.floor((data.byteLength - BINARY_HEADER_LENGTH) / 8);
17
- const infos = new Array(maxChunks);
16
+ const infos = [];
18
17
  let chunkStart = BINARY_HEADER_INTS * 4;
19
- let chunkCount = 0;
20
18
  while (chunkStart < data.byteLength) {
21
19
  const chunkInfo = getChunkInfo(chunkStart, data);
22
- infos[chunkCount++] = chunkInfo;
20
+ infos.push(chunkInfo);
23
21
  chunkStart += chunkInfo.length + BINARY_CHUNK_HEADER_INTS * 4;
24
22
  }
25
-
26
- // Trim array to actual size
27
- return infos.slice(0, chunkCount);
23
+ return infos;
28
24
  }
29
25
  function getJsonFromChunk(chunkInfo, data) {
26
+ const chunkLength = chunkInfo.length;
30
27
  const jsonStart = (BINARY_HEADER_INTS + BINARY_CHUNK_HEADER_INTS) * 4;
31
- const jsonView = new Uint8Array(data, jsonStart, chunkInfo.length);
32
- const decoder = new TextDecoder('utf-8');
33
- const jsonString = decoder.decode(jsonView);
34
- return JSON.parse(jsonString);
28
+ const jsonSlice = new Uint8Array(data, jsonStart, chunkLength);
29
+ const stringBuffer = BinaryHelper.arrayBufferToString(jsonSlice);
30
+ return JSON.parse(stringBuffer);
35
31
  }
36
32
  function getBufferFromChunk(chunkInfo, data) {
37
33
  return data.slice(chunkInfo.start, chunkInfo.start + chunkInfo.length);
38
34
  }
39
35
  function parseGLB(data) {
40
- if (data.byteLength < BINARY_HEADER_LENGTH) {
41
- throw new Error('Invalid GLB: File too small');
42
- }
43
-
44
- // Cache DataView
36
+ let json;
37
+ const buffers = [];
45
38
  const headerView = new DataView(data, 0, BINARY_HEADER_LENGTH);
46
- const magic = new Uint8Array(data, 0, 4);
47
39
  const header = {
48
- magic: BinaryHelper.arrayBufferToString(magic),
40
+ magic: BinaryHelper.arrayBufferToString(new Uint8Array(data, 0, 4)),
49
41
  version: headerView.getUint32(4, true),
50
42
  length: headerView.getUint32(8, true)
51
43
  };
52
44
  if (header.magic !== BINARY_HEADER_MAGIC) {
53
45
  throw new Error('Unsupported glTF-Binary header.');
54
- }
55
- if (header.version < 2.0) {
46
+ } else if (header.version < 2.0) {
56
47
  throw new Error('Unsupported legacy binary file detected.');
57
48
  }
58
- if (header.length > data.byteLength) {
59
- throw new Error('Invalid GLB: Declared length exceeds file size');
60
- }
61
49
  const chunkInfos = getAllChunkInfos(data);
62
- let json = null;
63
- const buffers = [];
64
-
65
- // Process chunks sequentially
66
- for (let i = 0; i < chunkInfos.length; i++) {
67
- const chunkInfo = chunkInfos[i];
50
+ chunkInfos.forEach(chunkInfo => {
68
51
  if (chunkInfo.type === BINARY_CHUNK_TYPES.JSON && !json) {
69
52
  json = getJsonFromChunk(chunkInfo, data);
70
53
  } else if (chunkInfo.type === BINARY_CHUNK_TYPES.BIN) {
71
54
  buffers.push(getBufferFromChunk(chunkInfo, data));
72
55
  }
73
- }
56
+ });
74
57
  if (!json) {
75
58
  throw new Error('glTF-Binary: JSON content not found.');
76
59
  }
60
+ if (!buffers) {
61
+ throw new Error('glTF-Binary: Binary chunk not found.');
62
+ }
77
63
  return {
78
64
  json,
79
65
  buffers
@@ -0,0 +1,42 @@
1
+ import registerWebworker from 'webworker-promise/lib/register';
2
+
3
+ /**
4
+ *
5
+ * @param {ArrayBuffer} imageBuffer
6
+ * @param {string} mimeType
7
+ * @param {string} channel
8
+ * @returns {Promise<ImageData>}
9
+ */
10
+ registerWebworker(async _ref => {
11
+ let {
12
+ imageBuffer,
13
+ mimeType,
14
+ channel
15
+ } = _ref;
16
+ const channelsMap = {
17
+ r: 0,
18
+ g: 1,
19
+ b: 2
20
+ };
21
+ const blob = new Blob([imageBuffer], {
22
+ type: mimeType
23
+ });
24
+ const img = await createImageBitmap(blob);
25
+ const canvas = new OffscreenCanvas(img.width, img.height);
26
+ const ctx = canvas.getContext('2d');
27
+ ctx.drawImage(img, 0, 0, img.width, img.height);
28
+ const bitmap = ctx.getImageData(0, 0, img.width, img.height);
29
+ if (channel) {
30
+ const idx = channelsMap[channel];
31
+ for (let i = 0; i < bitmap.data.length; i += 4) {
32
+ const channelValue = bitmap.data[i + idx];
33
+ bitmap.data[i] = channelValue; // red channel
34
+ bitmap.data[i + 1] = channelValue; // green channel
35
+ bitmap.data[i + 2] = channelValue; // blue channel
36
+ }
37
+ }
38
+
39
+ return {
40
+ bitmap
41
+ };
42
+ });
@@ -210,24 +210,15 @@ class GLTFParser {
210
210
  if (accessor.bufferView) {
211
211
  const buffer = accessor.bufferView.buffer;
212
212
  const {
213
- ArrayType
213
+ ArrayType,
214
+ byteLength
214
215
  } = getAccessorArrayTypeAndLength(accessor, accessor.bufferView);
215
- const baseByteOffset = (accessor.bufferView.byteOffset || 0) + buffer.byteOffset;
216
- const byteOffset = baseByteOffset + (accessor.byteOffset || 0);
217
- let arrayBufferView;
216
+ const byteOffset = (accessor.bufferView.byteOffset || 0) + (accessor.byteOffset || 0) + buffer.byteOffset;
217
+ let slicedBufffer = buffer.arrayBuffer.slice(byteOffset, byteOffset + byteLength);
218
218
  if (accessor.bufferView.byteStride) {
219
- // Only extract if stride is not equal to element size
220
- if (accessor.bufferView.byteStride === accessor.bytesPerElement) {
221
- arrayBufferView = new ArrayType(buffer.arrayBuffer, byteOffset, accessor.count * accessor.components);
222
- } else {
223
- // Interleaved buffer, extract only needed bytes
224
- const interleavedBuffer = this.getValueFromInterleavedBuffer(buffer, byteOffset, accessor.bufferView.byteStride, accessor.bytesPerElement, accessor.count);
225
- arrayBufferView = new ArrayType(interleavedBuffer);
226
- }
227
- } else {
228
- arrayBufferView = new ArrayType(buffer.arrayBuffer, byteOffset, accessor.count * accessor.components);
219
+ slicedBufffer = this.getValueFromInterleavedBuffer(buffer, byteOffset, accessor.bufferView.byteStride, accessor.bytesPerElement, accessor.count);
229
220
  }
230
- accessor.value = arrayBufferView;
221
+ accessor.value = new ArrayType(slicedBufffer);
231
222
  }
232
223
  return accessor;
233
224
  }
@@ -149,7 +149,6 @@ async function createPolyDataFromGLTFMesh(primitive) {
149
149
  polyData.setStrips(cells);
150
150
  break;
151
151
  default:
152
- cells.delete();
153
152
  vtkWarningMacro('Invalid primitive draw mode. Ignoring connectivity.');
154
153
  }
155
154
  return polyData;
@@ -199,7 +198,15 @@ async function createPropertyFromGLTFMaterial(model, material, actor) {
199
198
  const sampler = tex.sampler;
200
199
  const image = await loadImage(tex.source);
201
200
  const diffuseTex = createVTKTextureFromGLTFTexture(image, sampler);
202
- property.setDiffuseTexture(diffuseTex);
201
+
202
+ // FIXME: Workaround for textures not showing up in WebGL
203
+ const viewAPI = model.renderer.getRenderWindow();
204
+ const isWebGL = viewAPI.getViews()[0].isA('vtkOpenGLRenderWindow');
205
+ if (isWebGL) {
206
+ actor.addTexture(diffuseTex);
207
+ } else {
208
+ property.setDiffuseTexture(diffuseTex);
209
+ }
203
210
  }
204
211
 
205
212
  // Handle metallic-roughness texture (metallicRoughnessTexture)
@@ -217,7 +224,7 @@ async function createPropertyFromGLTFMaterial(model, material, actor) {
217
224
  material.occlusionTexture.extensions;
218
225
  const tex = material.occlusionTexture.texture;
219
226
  const sampler = tex.sampler;
220
- const aoImage = await loadImage(tex.source);
227
+ const aoImage = await loadImage(tex.source, 'r');
221
228
  const aoTex = createVTKTextureFromGLTFTexture(aoImage, sampler);
222
229
  property.setAmbientOcclusionTexture(aoTex);
223
230
  }
@@ -292,8 +299,6 @@ function handlePrimitiveExtensions(nodeId, extensions, model) {
292
299
  case 'KHR_materials_variants':
293
300
  model.variantMappings.set(nodeId, extension.mappings);
294
301
  break;
295
- case 'KHR_draco_mesh_compression':
296
- break;
297
302
  default:
298
303
  vtkWarningMacro(`Unhandled extension: ${extensionName}`);
299
304
  }
@@ -309,7 +314,6 @@ async function createActorFromGTLFNode(worldMatrix) {
309
314
  const actor = vtkActor.newInstance();
310
315
  const mapper = vtkMapper.newInstance();
311
316
  mapper.setColorModeToDirectScalars();
312
- mapper.setInterpolateScalarsBeforeMapping(true);
313
317
  actor.setMapper(mapper);
314
318
  actor.setUserMatrix(worldMatrix);
315
319
  const polydata = vtkPolyData.newInstance();
@@ -326,7 +330,6 @@ async function createActorFromGTLFPrimitive(model, primitive, worldMatrix) {
326
330
  const actor = vtkActor.newInstance();
327
331
  const mapper = vtkMapper.newInstance();
328
332
  mapper.setColorModeToDirectScalars();
329
- mapper.setInterpolateScalarsBeforeMapping(true);
330
333
  actor.setMapper(mapper);
331
334
  actor.setUserMatrix(worldMatrix);
332
335
  const polydata = await createPolyDataFromGLTFMesh(primitive);
@@ -1,5 +1,7 @@
1
+ import WebworkerPromise from 'webworker-promise';
1
2
  import { m as macro } from '../../../macros2.js';
2
3
  import vtkTexture from '../../../Rendering/Core/Texture.js';
4
+ import { W as WorkerFactory } from '../../../_virtual/rollup-plugin-worker-loader__module_Sources/IO/Geometry/GLTFImporter/ORMTexture.worker.js';
3
5
  import { ARRAY_TYPES, COMPONENTS, BYTES, GL_SAMPLER } from './Constants.js';
4
6
 
5
7
  const {
@@ -81,18 +83,33 @@ function resolveUrl(url, originalPath) {
81
83
  /**
82
84
  * Loads image from buffer or URI
83
85
  * @param {*} image
86
+ * @param {*} channel
84
87
  * @returns
85
88
  */
86
- async function loadImage(image) {
89
+ async function loadImage(image, channel) {
90
+ let forceReLoad = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
91
+ // Initialize cache if it doesn't exist
92
+ if (!image.cache) {
93
+ image.cache = {};
94
+ }
95
+
96
+ // Return cached result for the channel if available and not forced to reload
97
+ if (!forceReLoad && image.cache[channel]) {
98
+ return image.cache[channel];
99
+ }
100
+ const worker = new WebworkerPromise(new WorkerFactory());
87
101
  if (image.bufferView) {
88
- const blob = new Blob([image.bufferView.data], {
89
- type: image.mimeType
90
- });
91
- const bitmap = await createImageBitmap(blob, {
92
- colorSpaceConversion: 'none',
93
- imageOrientation: 'flipY'
102
+ return worker.postMessage({
103
+ imageBuffer: image.bufferView.data,
104
+ mimeType: image.mimeType,
105
+ channel
106
+ }).then(result => {
107
+ // Cache the bitmap based on the channel
108
+ image.cache[channel] = result.bitmap;
109
+ return result.bitmap;
110
+ }).finally(() => {
111
+ worker.terminate();
94
112
  });
95
- return bitmap;
96
113
  }
97
114
  if (image.uri) {
98
115
  vtkWarningMacro('Falling back to image uri', image.uri);
@@ -100,6 +117,7 @@ async function loadImage(image) {
100
117
  const img = new Image();
101
118
  img.crossOrigin = 'Anonymous';
102
119
  img.onload = () => {
120
+ image.cache[channel] = img; // Cache the loaded image based on the channel
103
121
  resolve(img);
104
122
  };
105
123
  img.onerror = reject;
@@ -140,7 +158,7 @@ function createVTKTextureFromGLTFTexture(image, sampler, extensions) {
140
158
  texture.setEdgeClamp(true);
141
159
  }
142
160
  }
143
- texture.setImageBitmap(image);
161
+ texture.setJsImageData(image);
144
162
  return texture;
145
163
  }
146
164
 
@@ -0,0 +1,113 @@
1
+ import { Vector3 } from './../../types';
2
+ import { vtkObject } from './../../interfaces';
3
+ import vtkCompositeKeyboardManipulator from './CompositeKeyboardManipulator';
4
+ import vtkRenderWindowInteractor from './../../Rendering/Core/RenderWindowInteractor';
5
+ import vtkCamera from './../../Rendering/Core/Camera';
6
+ import vtkRenderer from './../../Rendering/Core/Renderer';
7
+
8
+ export interface vtkKeyboardCameraManipulator
9
+ extends vtkObject,
10
+ vtkCompositeKeyboardManipulator {
11
+ /**
12
+ * Returns whether a movement is ongoing.
13
+ */
14
+ inMotion(): boolean;
15
+
16
+ /**
17
+ * Reset the movement speed to be proportional to the longest length of the renderer's bounds.
18
+ */
19
+ resetMovementSpeed(): void;
20
+
21
+ /**
22
+ * Initialize a movement of the current camera.
23
+ */
24
+ startMovement(): void;
25
+
26
+ /**
27
+ * Cancel any ongoing camera movement.
28
+ */
29
+ endMovement(): void;
30
+
31
+ /**
32
+ * Update active camera direction, depending on currently pressed keys.
33
+ */
34
+ calculateCurrentDirection(): void;
35
+
36
+ /**
37
+ * Returns the direction vector of the given camera for the given key.
38
+ * @param key the movedkey
39
+ * @param camera the camera
40
+ */
41
+ getDirectionFromKey(key: KeyboardEvent['key'], camera: vtkCamera): Vector3;
42
+
43
+ /**
44
+ * Moves the given camera, in the given direction, at the given speed.
45
+ * @param camera the moved camera
46
+ * @param direction the direction of the movemnt
47
+ * @param speed the speed
48
+ */
49
+ moveCamera(camera: vtkCamera, direction: Vector3, speed: number): void;
50
+
51
+ /**
52
+ * Handles a keypress event.
53
+ * @param interactor the interactor
54
+ * @param renderer the renderer
55
+ * @param key the key
56
+ */
57
+ onKeyPress(
58
+ interactor: vtkRenderWindowInteractor,
59
+ renderer: vtkRenderer,
60
+ key: KeyboardEvent['key']
61
+ ): void;
62
+
63
+ /**
64
+ * Handles a keydown event.
65
+ * @param interactor the interactor
66
+ * @param renderer the renderer
67
+ * @param key the key
68
+ */
69
+ onKeyDown(
70
+ interactor: vtkRenderWindowInteractor,
71
+ renderer: vtkRenderer,
72
+ key: KeyboardEvent['key']
73
+ ): void;
74
+
75
+ /**
76
+ * Handles a keyup event.
77
+ * @param interactor the interactor
78
+ * @param renderer the renderer
79
+ * @param key the key
80
+ */
81
+ onKeyUp(
82
+ interactor: vtkRenderWindowInteractor,
83
+ renderer: vtkRenderer,
84
+ key: KeyboardEvent['key']
85
+ ): void;
86
+ }
87
+
88
+ export interface IKeyboardCameraManipulatorInitialValues {
89
+ movementSpeed?: number;
90
+ moveForwardKeys?: KeyboardEvent['key'][];
91
+ moveLeftKeys?: KeyboardEvent['key'][];
92
+ moveBackwardKeys?: KeyboardEvent['key'][];
93
+ moveRightKeys?: KeyboardEvent['key'][];
94
+ moveUpKeys?: KeyboardEvent['key'][];
95
+ moveDownKeys?: KeyboardEvent['key'][];
96
+ }
97
+
98
+ export function newInstance(
99
+ initialValues?: IKeyboardCameraManipulatorInitialValues
100
+ ): vtkKeyboardCameraManipulator;
101
+
102
+ export function extend(
103
+ publicAPI: object,
104
+ model: object,
105
+ initialValues?: IKeyboardCameraManipulatorInitialValues
106
+ ): void;
107
+
108
+ export const vtkKeyboardCameraManipulator: {
109
+ newInstance: typeof newInstance;
110
+ extend: typeof extend;
111
+ };
112
+
113
+ export default vtkKeyboardCameraManipulator;
@@ -36,12 +36,6 @@ export interface vtkActor extends vtkProp3D {
36
36
  */
37
37
  getBackfaceProperty(): vtkProperty;
38
38
 
39
- /**
40
- * Get the bounds for this mapper as [xmin, xmax, ymin, ymax,zmin, zmax].
41
- * @return {Bounds} The bounds for the mapper.
42
- */
43
- getBounds(): Bounds;
44
-
45
39
  /**
46
40
  * Check whether the opaque is forced or not.
47
41
  */
@@ -63,16 +57,6 @@ export interface vtkActor extends vtkProp3D {
63
57
  */
64
58
  getMapper(): Nullable<vtkMapper>;
65
59
 
66
- /**
67
- * Get the property object that controls this actors surface
68
- * properties. This should be an instance of a vtkProperty object. Every
69
- * actor must have a property associated with it. If one isn’t specified,
70
- * then one will be generated automatically. Multiple actors can share one
71
- * property object.
72
- * @return {vtkProperty} The property object
73
- */
74
- getProperty(): vtkProperty;
75
-
76
60
  /**
77
61
  * Check whether if the actor supports selection
78
62
  * @return {Boolean} true if the actor support selection.
@@ -111,11 +95,12 @@ export interface vtkActor extends vtkProp3D {
111
95
  */
112
96
  setMapper(mapper: vtkMapper): boolean;
113
97
 
114
- /**
115
- * Set the property object that controls this actors surface properties.
116
- * @param {vtkProperty} property The vtkProperty instance.
117
- */
98
+ // Inherited from vtkProp3D, but takes a vtkProperty instead of a generic vtkObject
99
+ getProperty(mapperInputPort?: number): vtkProperty;
100
+ getProperties(): vtkProperty[];
101
+ setProperty(mapperInputPort: number, property: vtkProperty): boolean;
118
102
  setProperty(property: vtkProperty): boolean;
103
+ setProperties(properties: vtkProperty[]): boolean;
119
104
  }
120
105
 
121
106
  /**
@@ -1,13 +1,7 @@
1
- import { mat4, vec3 } from 'gl-matrix';
2
1
  import { m as macro } from '../../macros2.js';
3
- import vtkBoundingBox from '../../Common/DataModel/BoundingBox.js';
4
2
  import vtkProp3D from './Prop3D.js';
5
3
  import vtkProperty from './Property.js';
6
4
 
7
- const {
8
- vtkDebugMacro
9
- } = macro;
10
-
11
5
  // ----------------------------------------------------------------------------
12
6
  // vtkActor methods
13
7
  // ----------------------------------------------------------------------------
@@ -29,11 +23,11 @@ function vtkActor(publicAPI, model) {
29
23
  return false;
30
24
  }
31
25
  // make sure we have a property
32
- if (!model.property) {
26
+ if (!model.properties[0]) {
33
27
  // force creation of a property
34
28
  publicAPI.getProperty();
35
29
  }
36
- let isOpaque = model.property.getOpacity() >= 1.0;
30
+ let isOpaque = model.properties[0].getOpacity() >= 1.0;
37
31
 
38
32
  // are we using an opaque texture, if any?
39
33
  isOpaque = isOpaque && (!model.texture || !model.texture.isTranslucent());
@@ -47,71 +41,17 @@ function vtkActor(publicAPI, model) {
47
41
  return false;
48
42
  }
49
43
  // make sure we have a property
50
- if (model.property === null) {
44
+ if (!model.properties[0]) {
51
45
  // force creation of a property
52
- publicAPI.setProperty(publicAPI.makeProperty());
46
+ publicAPI.getProperty();
53
47
  }
54
48
 
55
49
  // is this actor opaque ?
56
50
  return !publicAPI.getIsOpaque();
57
51
  };
58
52
  publicAPI.makeProperty = vtkProperty.newInstance;
59
- publicAPI.getProperty = () => {
60
- if (model.property === null) {
61
- model.property = publicAPI.makeProperty();
62
- }
63
- return model.property;
64
- };
65
- publicAPI.getBounds = () => {
66
- if (model.mapper === null) {
67
- return model.bounds;
68
- }
69
-
70
- // Check for the special case when the mapper's bounds are unknown
71
- const bds = model.mapper.getBounds();
72
- if (!bds || bds.length !== 6) {
73
- return bds;
74
- }
75
-
76
- // Check for the special case when the actor is empty.
77
- if (bds[0] > bds[1]) {
78
- model.mapperBounds = bds.concat(); // copy the mapper's bounds
79
- model.bounds = [1, -1, 1, -1, 1, -1];
80
- model.boundsMTime.modified();
81
- return bds;
82
- }
83
-
84
- // Check if we have cached values for these bounds - we cache the
85
- // values returned by model.mapper.getBounds() and we store the time
86
- // of caching. If the values returned this time are different, or
87
- // the modified time of this class is newer than the cached time,
88
- // then we need to rebuild.
89
- if (!model.mapperBounds || bds[0] !== model.mapperBounds[0] || bds[1] !== model.mapperBounds[1] || bds[2] !== model.mapperBounds[2] || bds[3] !== model.mapperBounds[3] || bds[4] !== model.mapperBounds[4] || bds[5] !== model.mapperBounds[5] || publicAPI.getMTime() > model.boundsMTime.getMTime()) {
90
- vtkDebugMacro('Recomputing bounds...');
91
- model.mapperBounds = bds.concat(); // copy the mapper's bounds
92
- const bbox = [];
93
- vtkBoundingBox.getCorners(bds, bbox);
94
- publicAPI.computeMatrix();
95
- const tmp4 = new Float64Array(16);
96
- mat4.transpose(tmp4, model.matrix);
97
- bbox.forEach(pt => vec3.transformMat4(pt, pt, tmp4));
98
-
99
- /* eslint-disable no-multi-assign */
100
- model.bounds[0] = model.bounds[2] = model.bounds[4] = Number.MAX_VALUE;
101
- model.bounds[1] = model.bounds[3] = model.bounds[5] = -Number.MAX_VALUE;
102
- /* eslint-enable no-multi-assign */
103
-
104
- model.bounds = model.bounds.map((d, i) => i % 2 === 0 ? bbox.reduce((a, b) => a > b[i / 2] ? b[i / 2] : a, d) : bbox.reduce((a, b) => a < b[(i - 1) / 2] ? b[(i - 1) / 2] : a, d));
105
- model.boundsMTime.modified();
106
- }
107
- return model.bounds;
108
- };
109
53
  publicAPI.getMTime = () => {
110
54
  let mt = superClass.getMTime();
111
- if (model.property !== null) {
112
- const time = model.property.getMTime();
113
- mt = time > mt ? time : mt;
114
- }
115
55
  if (model.backfaceProperty !== null) {
116
56
  const time = model.backfaceProperty.getMTime();
117
57
  mt = time > mt ? time : mt;
@@ -146,11 +86,9 @@ function vtkActor(publicAPI, model) {
146
86
 
147
87
  const DEFAULT_VALUES = {
148
88
  mapper: null,
149
- property: null,
150
89
  backfaceProperty: null,
151
90
  forceOpaque: false,
152
- forceTranslucent: false,
153
- bounds: [1, -1, 1, -1, 1, -1]
91
+ forceTranslucent: false
154
92
  };
155
93
 
156
94
  // ----------------------------------------------------------------------------
@@ -167,7 +105,6 @@ function extend(publicAPI, model) {
167
105
  macro.obj(model.boundsMTime);
168
106
 
169
107
  // Build VTK API
170
- macro.set(publicAPI, model, ['property']);
171
108
  macro.setGet(publicAPI, model, ['backfaceProperty', 'forceOpaque', 'forceTranslucent', 'mapper']);
172
109
 
173
110
  // Object methods
@@ -1,5 +1,5 @@
1
1
  import { mat3, mat4, quat, vec3 } from 'gl-matrix';
2
- import { Extent, Nullable } from './../../types';
2
+ import { Nullable } from './../../types';
3
3
  import { vtkOutputPort } from './../../interfaces';
4
4
  import {
5
5
  vtkAbstractMapper3D,
@@ -309,25 +309,6 @@ export interface vtkImageCPRMapper
309
309
  * @param imageData
310
310
  */
311
311
  setImageConnection(imageData: vtkOutputPort): void;
312
-
313
- /**
314
- * Tells the mapper to only update the specified extents.
315
- *
316
- * If there are zero extents, the mapper updates the entire volume texture.
317
- * Otherwise, the mapper will only update the texture by the specified extents
318
- * during the next render call.
319
- *
320
- * This array is cleared after a successful render.
321
- * @param extents
322
- */
323
- setUpdatedExtents(extents: Extent[]): boolean;
324
-
325
- /**
326
- * Retrieves the updated extents.
327
- *
328
- * This array is cleared after every successful render.
329
- */
330
- getUpdatedExtents(): Extent[];
331
312
  }
332
313
 
333
314
  /**
@@ -283,7 +283,6 @@ const defaultValues = initialValues => ({
283
283
  projectionSlabThickness: 1,
284
284
  projectionSlabNumberOfSamples: 1,
285
285
  projectionMode: ProjectionMode.MAX,
286
- updatedExtents: [],
287
286
  ...initialValues
288
287
  });
289
288
 
@@ -304,7 +303,7 @@ function extend(publicAPI, model) {
304
303
  });
305
304
 
306
305
  // Setters and getters
307
- macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'centerPoint', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection', 'projectionSlabThickness', 'projectionSlabNumberOfSamples', 'projectionMode', 'updatedExtents']);
306
+ macro.setGet(publicAPI, model, ['width', 'uniformOrientation', 'useUniformOrientation', 'centerPoint', 'preferSizeOverAccuracy', 'orientationArrayName', 'tangentDirection', 'bitangentDirection', 'normalDirection', 'projectionSlabThickness', 'projectionSlabNumberOfSamples', 'projectionMode']);
308
307
  CoincidentTopologyHelper.implementCoincidentTopologyMethods(publicAPI, model);
309
308
 
310
309
  // Object methods
@@ -1,5 +1,5 @@
1
1
  import { vtkObject } from './../../interfaces';
2
- import { Nullable } from './../../types';
2
+ import { Extent, Nullable } from './../../types';
3
3
  import vtkColorTransferFunction from './ColorTransferFunction';
4
4
  import vtkPiecewiseFunction from './../../Common/DataModel/PiecewiseFunction';
5
5
  import { InterpolationType } from './ImageProperty/Constants';
@@ -231,6 +231,25 @@ export interface vtkImageProperty extends vtkObject {
231
231
  * @param {Boolean} useLookupTableScalarRange
232
232
  */
233
233
  setUseLookupTableScalarRange(useLookupTableScalarRange: boolean): boolean;
234
+
235
+ /**
236
+ * Informs the mapper to only update the specified extents at the next render.
237
+ *
238
+ * If there are zero extents, the mapper updates the entire volume texture.
239
+ * Otherwise, the mapper will only update the texture by the specified extents
240
+ * during the next render call.
241
+ *
242
+ * This array is cleared after a successful render.
243
+ * @param extents
244
+ */
245
+ setUpdatedExtents(extents: Extent[]): boolean;
246
+
247
+ /**
248
+ * Retrieves the updated extents.
249
+ *
250
+ * This array is cleared after every successful render.
251
+ */
252
+ getUpdatedExtents(): Extent[];
234
253
  }
235
254
 
236
255
  /**