1 of 69

Developing with vtk.js

2 of 69

Acknowledgments

  • Presented By:
    • Forrest Li (Kitware)�
  • Contributors:
    • Forrest Li (Kitware)
    • Trinity Urban (MGH and OHIF)
    • Steve Pieper (Isomics)
    • Erik Ziegler (OHIF)
    • Gordon J. Harris (MGH and OHIF)
    • James A. Petts (OHIF)
    • Danny Brown (OHIF)
    • Stephen Aylward (Kitware)

3 of 69

Funding Sources

  • VTK.js / Kitware
    • NIH NINDS R44NS081792
    • NIH NINDS R42NS086295
    • NIH NIBIB and NIGMS R01EB021396
    • NIH NIBIB R01EB014955
  • Isomics
    • NIH P41 EB015902
  • OHIF
    • NIH U24 CA199460

4 of 69

Course Outline

  1. Introduction to vtk.js and OHIF
  2. Starting a vtk.js project
  3. vtk.js: Architecture, itk.js, widgets, and more
  4. OHIF + vtk.js integration
  5. Advanced vtk.js: WebGL and GLSL

5 of 69

Requirements (basic)

  • A modern web browser that supports WebGL
    • Don’t know? Test it out here: https://get.webgl.org/
    • Good graphics card is preferred
  • A text editor

WebGL2

(recommended)

WebGL 1

(not recommended)

6 of 69

Requirements (development)

  • node.js (https://nodejs.org/en/)
  • npm (in node.js install) or yarn (https://yarnpkg.com/en/)
  • A terminal emulator
    • Familiarity with working in a shell/command line
  • Familiarity with browser devtools

7 of 69

Source Files for this Demo

8 of 69

The super simple example

Only browser + text editor needed

9 of 69

🌟 Only a single

HTML file needed!

File: standalone.html

10 of 69

Import VTK.js

11 of 69

Set up the VTK.js RenderWindow and Renderer

12 of 69

Attach WebGL RenderWindow implementation

13 of 69

Attach interactive trackball controls

14 of 69

Construct our rendering pipeline for a cone

15 of 69

Center camera on cone and trigger the render pipeline

16 of 69

Super simple example

  • Great for one-off demos
  • Only need a browser!
    • No need to pull in node.js/npm/entire development ecosystem
  • Ease of prototyping

  • 💡 Exercises
    • Use a different surface source, like vtkCylinderSource, vtkSphereSource, or vtkPlaneSource
    • Modify some properties of the sources! e.g. cone.setHeight(3.0)

17 of 69

Project Creation Example

node + npm + everything else

18 of 69

Project Creation: Application Structure

  • Example application structure
    • We will make these files as we go�through the example
  • src/: source code
  • dist/: final bundled code

  • See the examples for final project

19 of 69

Project Creation

$ npm init

20 of 69

Installing tooling + dependencies

$ npm install --save vtk.js�$ npm install --save-dev kw-web-suite

Brings in:�

  • webpack
  • babel
  • eslint
  • prettier
  • webpack loaders (css, shaders, etc.)
  • webpack-dev-server
  • ...and more

21 of 69

Creating initial files

  • Main javascript entry point: src/index.js
  • Browser entry point: dist/index.html
  • Webpack build configuration: webpack.config.js

22 of 69

Creating files: dist/index.html

23 of 69

Creating files: src/index.js

  • Start with a simple import to verify the build worked

24 of 69

Creating files: webpack.config.js

25 of 69

Creating files: webpack.config.js

vtk.js webpack rules required

26 of 69

Building our example

Two ways:

  • npx webpack --progress
    • Requires installing “npx”: npm install -g npx
  • npm run build or npm run dev
    • Requires the following changes to package.json:

27 of 69

Build results

You should now have a file: dist/app.js

Open index.html in your browser, open devtools (F12 on most browsers):

Success!

28 of 69

Cone Example: revisited

Let’s “rewrite” our old code

29 of 69

Rewriting our Cone Example

  • vtkGenericRenderWindow does all of the setup for the RenderWindow, Renderer, and Interactor.

30 of 69

Rewriting our Cone Example

31 of 69

Rewriting our Cone Example

Example source file: vtk.js-examples/cone.js

32 of 69

Explanation: Rendering Pipeline

33 of 69

Explanation: Rendering Pipeline

  • ConeSource supplies data
  • Data goes through Mapper
  • Mapper is attached to Actor
  • Renderer holds many Actors
  • RenderWindow holds many�Renderers

34 of 69

Examining ConeSource

  • vtkConeSource is a VTK filter
  • Algorithm that outputs vtkPolyData
    • A collection of vertices, lines, and surfaces
    • A basic vtk.js datatype
  • ConeSource algorithm: 0 inputs, 1 output

35 of 69

VTK.js Filters: Example

  • Simple example: vtkOutlineFilter
  • vtkOutlineFilter transforms input PolyData into an outline box

36 of 69

VTK Filters: Example

37 of 69

VTK Filters: Pipelines

  • InputData/OutputData
    • Static: need to call getOutputData()�to get updated data
  • InputConnection/OutputPort
    • Reactive: getting the output data of�a chain of filters will fetch the latest�data given the existing parameters
  • Data can go through multiple pipelines

38 of 69

VTK Filters: Example Result

Example source file: vtk.js-examples/cone-filter.js

39 of 69

Volumes and Images

3D volumes and 2D slices

40 of 69

Volume and Slice Rendering

  • 3D volumes rendered in scene
    • Including oriented images!
  • Color Transfer Functions
  • Opacity
  • Slicing
  • Loading remote datasets

41 of 69

Volume Rendering Example

Three steps:

  1. Setting up the volume rendering pipeline
  2. Loading a remote dataset
  3. Rendering the volume

42 of 69

Volume Rendering Pipeline

  • Set up the vtkVolume and vtkVolumeMapper
  • Very similar to the cone setup
  • What data goes into the mapper?

43 of 69

Loading a Remote Dataset

  • vtk.js/Sources/IO/Core/HttpDataSetReader
    • Loads a custom vtk.js-specific file format
    • Data is automatically loaded into a polydata or image
    • Example
  • Browser Fetch API with I/O readers
    • Downloads raw data from an endpoint
    • Must manually load that data into usable vtk.js polydata or image
      • XMLImageDataReader, XMLPolyDataReader, itk.js, etc.
    • Alternative for older browsers: XMLHttpRequest API

44 of 69

Fetch Example

  • 💡 Throughout these examples, feel free to try fetching and rendering your own data! Make sure the data is CORS accessible.

45 of 69

Loading a Remote Volume

  • HttpDataSetReader is an algorithm that outputs a dataset

46 of 69

Volume Rendering: 1st result

  • Black/grey/white
  • No opacity
  • Not terribly useful - cannot see�Inside

Source file: volume.js

47 of 69

Volume Rendering: Opacity and Color

  • Opacity function: determines which voxels are transparent
  • Color transfer function: Determines which voxels map to what color

48 of 69

Volume Rendering: Opacity

  • Create a vtkPiecewiseFunction
  • Linear opacity function maps [0, 256] to [0, 1]
  • Actor properties: Opacity, color, lighting, etc.

49 of 69

Volume Rendering: Color Transfer Function

  • Create a vtkColorTransferFunction
  • Apply a colormap, or set points manually
    • Cool to Warm, Matlab colors, ERDC colors, etc.
  • Set mapping range to be volume data range

50 of 69

Volume Rendering: 2nd result

  • Pixels close to 0 are now transparent
  • Pixels are mapped according to the�colormap “Warm to Cool”
  • Can see internal volume structures

Source file: volume-transfer.js

51 of 69

Piecewise Gaussian Widget

52 of 69

Volume Rendering

  • MPR
  • Max, Min, Avg Intensity Projection
  • Multiple component volumes
  • Interpolation types

  • 💡 Exercises!
    • Change the scalar opacity function. More advanced: use vtkPiecewiseGaussianWidget
    • Change up the color transfer function with a different preset: All presets
    • Try rendering an oriented image dataset

53 of 69

Volume Slicing

  • vtkVolume -> vtkImageSlice
  • vtkVolumeMapper -> vtkImageMapper
  • Parallel camera projection
  • 2D image interactor
    • window/level
    • slicing

54 of 69

Volume Slicing

55 of 69

Volume Slicing

Use image slicing interactivity (slice scroll and mouse window/level)

56 of 69

Volume Slicing

Need to set slice at focal point

57 of 69

Volume Slicing

Sets default window/level

58 of 69

Volume Slicing

  • Play around with the mouse for window/level�controls
  • Scroll through slices with mouse wheel or�trackpad scrolling

Source file: image-slicing.js

59 of 69

Widgets and Interactions

  • Add lines and controls to a scene
  • Paint or contour an image
  • Place landmarks
  • Select regions
  • ...and more!

60 of 69

Widget Example: Cropping Widget

  • Interactive widget to crop a volume
  • Demonstrates handle and dataset interactions in 2D and 3D
  • Requires the vtkCropFilter
    • This performs the actual cropping of the dataset

61 of 69

Widgets Overview

  • Widget Manager
    • Is associated with a renderer
    • Manages widgets in that renderer
  • Widgets
    • Consists of a widget state and a widget factory
    • Widgets constructed via factory are bound to renderers
    • Representations derive from widget state
    • MVC architecture

62 of 69

Adding Crop Widget

63 of 69

Adding Crop Widget

Attaches renderer to widget manager

64 of 69

Adding Crop Widget

A view widget is an instance of a widget in a renderer.

65 of 69

Adding Crop Widget

When the crop widget updates, we crop our image.

66 of 69

Adding Crop Widget

  • vtkHttpDataSetReader 🠆 vtkCropFilter 🠆 cropped image

Initialize the crop filter with the volume

67 of 69

Crop Widget

  • Crop your volume via the green handles
  • 💡 Check out other vtk.js widgets on the�vtk.js examples page.
    • Play with the widget API by turning off�certain handles

Source file: widgets.js

68 of 69

Conclusion

  • Demonstrated examples for:
    • Geometry rendering
    • Filters
    • Volume rendering
    • Slice rendering
    • Interactive widgets
  • More: https://kitware.github.io/vtk-js/examples/

69 of 69

Next Time

Next course (#3):

Digging into vtk.js: Architecture and more