Skip to content

Commit fc6fd89

Browse files
committed
docs(XR): Add Looking Glass support to cinematic rendering examples
Adds Looking Glass WebXR support to two WebXR cinematic rendering examples. Note that the number of views is intentionally constrained in `WebXRHeadFullVolumeCVR` to address observed performance issues. `WebXRChestCTBlendedCVR` is excluded from changes due to image size and subsequent rendering performance.
1 parent 46ceafe commit fc6fd89

File tree

2 files changed

+88
-36
lines changed

2 files changed

+88
-36
lines changed

Examples/Volume/WebXRHeadFullVolumeCVR/index.js

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,43 @@ const ofun = vtkPiecewiseFunction.newInstance();
5656

5757
const {
5858
fileURL = 'https://data.kitware.com/api/v1/file/59de9dca8d777f31ac641dc2/download',
59+
xrSessionType = null,
5960
} = vtkURLExtract.extractURLParameters();
6061

62+
// Validate input parameters
63+
let requestedXrSessionType = xrSessionType;
64+
if (!Object.values(XrSessionTypes).includes(requestedXrSessionType)) {
65+
console.warn(
66+
'Could not parse requested XR session type: ',
67+
requestedXrSessionType
68+
);
69+
requestedXrSessionType = null;
70+
}
71+
72+
if (requestedXrSessionType === XrSessionTypes.LookingGlassVR) {
73+
// Import the Looking Glass WebXR Polyfill override
74+
// Assumes that the Looking Glass Bridge native application is already running.
75+
// See https://docs.lookingglassfactory.com/developer-tools/webxr
76+
import(
77+
// eslint-disable-next-line import/no-unresolved, import/extensions
78+
/* webpackIgnore: true */ 'https://unpkg.com/@lookingglass/[email protected]/dist/@lookingglass/bundle/webxr.js'
79+
).then((obj) => {
80+
// eslint-disable-next-line no-new
81+
new obj.LookingGlassWebXRPolyfill({ numViews: 12 });
82+
});
83+
} else if (requestedXrSessionType === null) {
84+
// Determine supported session type
85+
navigator.xr.isSessionSupported('immersive-ar').then((arSupported) => {
86+
if (arSupported) {
87+
requestedXrSessionType = XrSessionTypes.MobileAR;
88+
} else {
89+
navigator.xr.isSessionSupported('immersive-vr').then((vrSupported) => {
90+
requestedXrSessionType = vrSupported ? XrSessionTypes.HmdVR : null;
91+
});
92+
}
93+
});
94+
}
95+
6196
HttpDataAccessHelper.fetchBinary(fileURL).then((fileContents) => {
6297
// Read data
6398
vtiReader.parseAsArrayBuffer(fileContents);
@@ -110,7 +145,6 @@ HttpDataAccessHelper.fetchBinary(fileURL).then((fileContents) => {
110145
renderWindow.render();
111146

112147
// Add button to launch AR (default) or VR scene
113-
let xrSessionType = 0;
114148
const xrButton = document.createElement('button');
115149
let enterText = 'XR not available!';
116150
const exitText = 'Exit XR';
@@ -119,28 +153,20 @@ HttpDataAccessHelper.fetchBinary(fileURL).then((fileContents) => {
119153
navigator.xr !== undefined &&
120154
fullScreenRenderer.getApiSpecificRenderWindow().getXrSupported()
121155
) {
122-
navigator.xr.isSessionSupported('immersive-ar').then((arSupported) => {
123-
if (arSupported) {
124-
xrSessionType = XrSessionTypes.MobileAR;
125-
enterText = 'Start AR';
126-
xrButton.textContent = enterText;
127-
} else {
128-
navigator.xr.isSessionSupported('immersive-vr').then((vrSupported) => {
129-
if (vrSupported) {
130-
xrSessionType = XrSessionTypes.HmdVR;
131-
enterText = 'Start VR';
132-
xrButton.textContent = enterText;
133-
}
134-
});
135-
}
136-
});
156+
enterText =
157+
requestedXrSessionType === XrSessionTypes.MobileAR
158+
? 'Start AR'
159+
: 'Start VR';
160+
xrButton.textContent = enterText;
137161
}
138162
xrButton.addEventListener('click', () => {
139163
if (xrButton.textContent === enterText) {
140-
if (xrSessionType === XrSessionTypes.MobileAR) {
164+
if (requestedXrSessionType === XrSessionTypes.MobileAR) {
141165
fullScreenRenderer.setBackground([0, 0, 0, 0]);
142166
}
143-
fullScreenRenderer.getApiSpecificRenderWindow().startXR(xrSessionType);
167+
fullScreenRenderer
168+
.getApiSpecificRenderWindow()
169+
.startXR(requestedXrSessionType);
144170
xrButton.textContent = exitText;
145171
} else {
146172
fullScreenRenderer.setBackground([...background, 255]);

Examples/Volume/WebXRHeadGradientCVR/index.js

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,43 @@ const ofun = vtkPiecewiseFunction.newInstance();
5656

5757
const {
5858
fileURL = 'https://data.kitware.com/api/v1/file/59de9dca8d777f31ac641dc2/download',
59+
xrSessionType = null,
5960
} = vtkURLExtract.extractURLParameters();
6061

62+
// Validate input parameters
63+
let requestedXrSessionType = xrSessionType;
64+
if (!Object.values(XrSessionTypes).includes(requestedXrSessionType)) {
65+
console.warn(
66+
'Could not parse requested XR session type: ',
67+
requestedXrSessionType
68+
);
69+
requestedXrSessionType = null;
70+
}
71+
72+
if (requestedXrSessionType === XrSessionTypes.LookingGlassVR) {
73+
// Import the Looking Glass WebXR Polyfill override
74+
// Assumes that the Looking Glass Bridge native application is already running.
75+
// See https://docs.lookingglassfactory.com/developer-tools/webxr
76+
import(
77+
// eslint-disable-next-line import/no-unresolved, import/extensions
78+
/* webpackIgnore: true */ 'https://unpkg.com/@lookingglass/[email protected]/dist/@lookingglass/bundle/webxr.js'
79+
).then((obj) => {
80+
// eslint-disable-next-line no-new
81+
new obj.LookingGlassWebXRPolyfill();
82+
});
83+
} else if (requestedXrSessionType === null) {
84+
// Determine supported session type
85+
navigator.xr.isSessionSupported('immersive-ar').then((arSupported) => {
86+
if (arSupported) {
87+
requestedXrSessionType = XrSessionTypes.MobileAR;
88+
} else {
89+
navigator.xr.isSessionSupported('immersive-vr').then((vrSupported) => {
90+
requestedXrSessionType = vrSupported ? XrSessionTypes.HmdVR : null;
91+
});
92+
}
93+
});
94+
}
95+
6196
HttpDataAccessHelper.fetchBinary(fileURL).then((fileContents) => {
6297
// Read data
6398
vtiReader.parseAsArrayBuffer(fileContents);
@@ -107,7 +142,6 @@ HttpDataAccessHelper.fetchBinary(fileURL).then((fileContents) => {
107142
renderWindow.render();
108143

109144
// Add button to launch AR (default) or VR scene
110-
let xrSessionType = 0;
111145
const xrButton = document.createElement('button');
112146
let enterText = 'XR not available!';
113147
const exitText = 'Exit XR';
@@ -116,28 +150,20 @@ HttpDataAccessHelper.fetchBinary(fileURL).then((fileContents) => {
116150
navigator.xr !== undefined &&
117151
fullScreenRenderer.getApiSpecificRenderWindow().getXrSupported()
118152
) {
119-
navigator.xr.isSessionSupported('immersive-ar').then((arSupported) => {
120-
if (arSupported) {
121-
xrSessionType = XrSessionTypes.MobileAR;
122-
enterText = 'Start AR';
123-
xrButton.textContent = enterText;
124-
} else {
125-
navigator.xr.isSessionSupported('immersive-vr').then((vrSupported) => {
126-
if (vrSupported) {
127-
xrSessionType = XrSessionTypes.HmdVR;
128-
enterText = 'Start VR';
129-
xrButton.textContent = enterText;
130-
}
131-
});
132-
}
133-
});
153+
enterText =
154+
requestedXrSessionType === XrSessionTypes.MobileAR
155+
? 'Start AR'
156+
: 'Start VR';
157+
xrButton.textContent = enterText;
134158
}
135159
xrButton.addEventListener('click', () => {
136160
if (xrButton.textContent === enterText) {
137-
if (xrSessionType === XrSessionTypes.MobileAR) {
161+
if (requestedXrSessionType === XrSessionTypes.MobileAR) {
138162
fullScreenRenderer.setBackground([0, 0, 0, 0]);
139163
}
140-
fullScreenRenderer.getApiSpecificRenderWindow().startXR(xrSessionType);
164+
fullScreenRenderer
165+
.getApiSpecificRenderWindow()
166+
.startXR(requestedXrSessionType);
141167
xrButton.textContent = exitText;
142168
} else {
143169
fullScreenRenderer.setBackground([...background, 255]);

0 commit comments

Comments
 (0)