Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Documentation/content/docs/develop_webxr.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ vtk.js supports virtual and augmented reality rendering via the [WebXR device AP

[![VR Cone Example][VrCone]](../examples/VR.html)
[![SkyboxViewer Example][SkyboxViewerVR]](../examples/SkyboxViewer.html?fileURL=https://data.kitware.com/api/v1/file/5ae8a89c8d777f0685796bae/download)
[![XR Volume Example][WebXRVolume]](../examples/WebXRVolume.html)

</div>

Expand All @@ -51,6 +52,7 @@ vtk.js supports virtual and augmented reality rendering via the [WebXR device AP
[![GeometryViewer Example][GeometryViewer]](../examples/GeometryViewer.html?fileURL=https://data.kitware.com/api/v1/item/59de9de58d777f31ac641dc5/download)
[![GeometryViewer Brain Blood Vessels][GeometryViewerBrainBloodVessels]](../examples/GeometryViewer/GeometryViewer.html?fileURL=[https://data.kitware.com/api/v1/file/61f041f14acac99f42c2ff9a/download,https://data.kitware.com/api/v1/file/61f042024acac99f42c2ffa6/download,https://data.kitware.com/api/v1/file/61f042b74acac99f42c30079/download])
[![GeometryViewer Chest CT][GeometryViewerchestCT]](../examples/GeometryViewer/GeometryViewer.html?fileURL=[https://data.kitware.com/api/v1/file/61f044354acac99f42c30276/download,https://data.kitware.com/api/v1/file/61f0440f4acac99f42c30191/download,https://data.kitware.com/api/v1/file/61f044204acac99f42c30267/download])
[![XR Volume Example][WebXRVolume]](../examples/WebXRVolume.html)

</div>

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions Examples/Volume/WebXRVolume/WebXRVolume.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
body {
display: flex;
align-items: center;
justify-content: center;
}

button {
position: absolute;
left: 10px;
top: 10px;
width: 200px;
z-index: 2;
cursor: pointer;
}
146 changes: 146 additions & 0 deletions Examples/Volume/WebXRVolume/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import 'vtk.js/Sources/favicon';

// Load the rendering pieces we want to use (for both WebGL and WebGPU)
import 'vtk.js/Sources/Rendering/Profiles/Volume';

// Force DataAccessHelper to have access to various data source
import 'vtk.js/Sources/IO/Core/DataAccessHelper/HtmlDataAccessHelper';
import 'vtk.js/Sources/IO/Core/DataAccessHelper/JSZipDataAccessHelper';

import vtkColorTransferFunction from 'vtk.js/Sources/Rendering/Core/ColorTransferFunction';
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
import HttpDataAccessHelper from 'vtk.js/Sources/IO/Core/DataAccessHelper/HttpDataAccessHelper';
import vtkPiecewiseFunction from 'vtk.js/Sources/Common/DataModel/PiecewiseFunction';
import vtkURLExtract from 'vtk.js/Sources/Common/Core/URLExtract';
import vtkVolume from 'vtk.js/Sources/Rendering/Core/Volume';
import vtkVolumeMapper from 'vtk.js/Sources/Rendering/Core/VolumeMapper';
import vtkXMLImageDataReader from 'vtk.js/Sources/IO/XML/XMLImageDataReader';

import './WebXRVolume.module.css';

// ----------------------------------------------------------------------------
// Standard rendering code setup
// ----------------------------------------------------------------------------

const background = [0, 0, 0];
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
background,
});
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();

// ----------------------------------------------------------------------------
// Set up pipeline objects
// ----------------------------------------------------------------------------

const vtiReader = vtkXMLImageDataReader.newInstance();
const actor = vtkVolume.newInstance();
const mapper = vtkVolumeMapper.newInstance();
mapper.setInputConnection(vtiReader.getOutputPort());
actor.setMapper(mapper);
renderer.addVolume(actor);

// create color and opacity transfer functions
const ctfun = vtkColorTransferFunction.newInstance();
const ofun = vtkPiecewiseFunction.newInstance();

// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------

const {
fileURL = 'https://data.kitware.com/api/v1/file/59de9dca8d777f31ac641dc2/download',
} = vtkURLExtract.extractURLParameters();

HttpDataAccessHelper.fetchBinary(fileURL).then((fileContents) => {
// Read data
vtiReader.parseAsArrayBuffer(fileContents);
const data = vtiReader.getOutputData(0);
const dataArray =
data.getPointData().getScalars() || data.getPointData().getArrays()[0];
const dataRange = dataArray.getRange();

// Restyle visual appearance
const sampleDistance =
0.7 *
Math.sqrt(
data
.getSpacing()
.map((v) => v * v)
.reduce((a, b) => a + b, 0)
);
mapper.setSampleDistance(sampleDistance);

ctfun.addRGBPoint(dataRange[0], 0.0, 0.3, 0.3);
ctfun.addRGBPoint(dataRange[1], 1.0, 1.0, 1.0);
ofun.addPoint(dataRange[0], 0.0);
ofun.addPoint((dataRange[1] - dataRange[0]) / 4, 0.0);
ofun.addPoint(dataRange[1], 0.5);
actor.getProperty().setRGBTransferFunction(0, ctfun);
actor.getProperty().setScalarOpacity(0, ofun);
actor.getProperty().setInterpolationTypeToLinear();

// Set up rendering
renderer.resetCamera();
renderWindow.render();

// Add button to launch AR (default) or VR scene
const VR = 1;
const AR = 2;
let xrSessionType = 0;
const xrButton = document.createElement('button');
let enterText = 'XR not available!';
const exitText = 'Exit XR';
xrButton.textContent = enterText;
if (
navigator.xr !== undefined &&
fullScreenRenderer.getApiSpecificRenderWindow().getXrSupported()
) {
navigator.xr.isSessionSupported('immersive-ar').then((arSupported) => {
if (arSupported) {
xrSessionType = AR;
enterText = 'Start AR';
xrButton.textContent = enterText;
} else {
navigator.xr.isSessionSupported('immersive-vr').then((vrSupported) => {
if (vrSupported) {
xrSessionType = VR;
enterText = 'Start VR';
xrButton.textContent = enterText;
}
});
}
});
}
xrButton.addEventListener('click', () => {
if (xrButton.textContent === enterText) {
if (xrSessionType === AR) {
fullScreenRenderer.setBackground([0, 0, 0, 0]);
}
fullScreenRenderer
.getApiSpecificRenderWindow()
.startXR(xrSessionType === AR);
xrButton.textContent = exitText;
} else {
fullScreenRenderer.setBackground([...background, 255]);
fullScreenRenderer
.getApiSpecificRenderWindow()
.stopXR(xrSessionType === AR);
xrButton.textContent = enterText;
}
});
document.querySelector('.content').appendChild(xrButton);
});

// -----------------------------------------------------------
// Make some variables global so that you can inspect and
// modify objects in your browser's developer console:
// -----------------------------------------------------------

global.source = vtiReader;
global.mapper = mapper;
global.actor = actor;
global.ctfun = ctfun;
global.ofun = ofun;
global.renderer = renderer;
global.renderWindow = renderWindow;
17 changes: 17 additions & 0 deletions Examples/Volume/WebXRVolume/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

### WebXR Volume Viewer

vtk.js supports volume rendering in virtual and augmented reality environments for WebXR compatible systems.

This example loads and renders a .vti volume file found [here](https://data.kitware.com/api/v1/file/59de9dca8d777f31ac641dc2/download). Press the "Enter VR" or "Enter AR" button to launch an XR rendering on a WebXR-compatible system. To specify other .vti files, provide the `?fileURL=<link>` URL parameter.

Volume rendering can be processor-intensive. Smaller volumes may give better performance on mobile devices.

- [binary-head.vti](https://kitware.github.io/vtk-js/examples/WebXRVolume/WebXRVolume.html?fileURL=https://data.kitware.com/api/v1/file/59de9dca8d777f31ac641dc2/download) 15.6 MB
- [binary-head-2.vti](https://kitware.github.io/vtk-js/examples/WebXRVolume/WebXRVolume.html?fileURL=https://data.kitware.com/api/v1/file/629921a64acac99f429a45a7/download) 361 kB
- [tiny-image.vti](https://kitware.github.io/vtk-js/examples/WebXRVolume/WebXRVolume.html?fileURL=https://data.kitware.com/api/v1/file/624320e74acac99f42254a25/download) 1.6 kB

### See Also

[Full list of WebXR Examples](https://kitware.github.io/vtk-js/docs/develop_webxr.html)
[VolumeViewer Example](https://kitware.github.io/vtk-js/examples/VolumeViewer.html)
2 changes: 2 additions & 0 deletions Sources/Rendering/OpenGL/RenderWindow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,8 @@ function vtkOpenGLRenderWindow(publicAPI, model) {

camera.setPhysicalScale(physicalScale);
camera.setPhysicalTranslation(physicalTranslation);
// Clip at 0.1m, 100.0m in physical space by default
camera.setClippingRange(0.1 * physicalScale, 100.0 * physicalScale);
};

publicAPI.stopXR = async () => {
Expand Down