Skip to content

Commit e11f54d

Browse files
authored
Merge pull request #2171 from tbirdso/webxr-test
feat(XR): Update to WebXR functionality in OpenGL RenderWindow
2 parents 2ea94a2 + fda3b34 commit e11f54d

File tree

4 files changed

+153
-242
lines changed

4 files changed

+153
-242
lines changed

Examples/Applications/SkyboxViewer/index.js

Lines changed: 23 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ import 'vtk.js/Sources/Rendering/Profiles/Geometry';
66
import HttpDataAccessHelper from 'vtk.js/Sources/IO/Core/DataAccessHelper/HttpDataAccessHelper';
77
import macro from 'vtk.js/Sources/macros';
88
import vtkDeviceOrientationToCamera from 'vtk.js/Sources/Interaction/Misc/DeviceOrientationToCamera';
9-
import vtkForwardPass from 'vtk.js/Sources/Rendering/OpenGL/ForwardPass';
109
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
11-
import vtkRadialDistortionPass from 'vtk.js/Sources/Rendering/OpenGL/RadialDistortionPass';
12-
import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer';
1310
import vtkSkybox from 'vtk.js/Sources/Rendering/Core/Skybox';
1411
import vtkSkyboxReader from 'vtk.js/Sources/IO/Misc/SkyboxReader';
1512
import vtkURLExtract from 'vtk.js/Sources/Common/Core/URLExtract';
@@ -41,14 +38,9 @@ let autoInit = true;
4138
const cameraFocalPoint = userParams.direction || [0, 0, -1];
4239
const cameraViewUp = userParams.up || [0, 1, 0];
4340
const cameraViewAngle = userParams.viewAngle || 100;
44-
const enableVR = !!userParams.vr;
4541
const eyeSpacing = userParams.eye || 0.0;
4642
const grid = userParams.debug || false;
4743
const autoIncrementTimer = userParams.timer || 0;
48-
const disableTouchNext = userParams.disableTouch || false;
49-
const distk1 = userParams.k1 || 0.2;
50-
const distk2 = userParams.k2 || 0.0;
51-
const cameraCenterY = userParams.centerY || 0.0;
5244

5345
const body = document.querySelector('body');
5446
let fullScreenMetod = null;
@@ -151,10 +143,8 @@ function createVisualization(container, mapReader) {
151143
const mainRenderer = fullScreenRenderer.getRenderer();
152144
const interactor = fullScreenRenderer.getInteractor();
153145
const actor = vtkSkybox.newInstance();
154-
let camera = mainRenderer.getActiveCamera();
155-
let leftRenderer = null;
156-
let rightRenderer = null;
157-
let updateCameraCallBack = mainRenderer.resetCameraClippingRange;
146+
const camera = mainRenderer.getActiveCamera();
147+
const updateCameraCallBack = mainRenderer.resetCameraClippingRange;
158148

159149
// Connect viz pipeline
160150
actor.addTexture(mapReader.getOutputData());
@@ -189,116 +179,28 @@ function createVisualization(container, mapReader) {
189179
updateSkybox(allPositions[nextIdx]);
190180
}
191181

192-
if (enableVR && vtkDeviceOrientationToCamera.isDeviceOrientationSupported()) {
193-
// vtkMobileVR.getVRHeadset().then((headset) => {
194-
// console.log('got headset');
195-
// console.log(headset);
196-
// console.log(vtkMobileVR.hardware);
197-
// });
198-
199-
leftRenderer = vtkRenderer.newInstance();
200-
rightRenderer = vtkRenderer.newInstance();
201-
202-
// Configure left/right renderers
203-
leftRenderer.setViewport(0, 0, 0.5, 1);
204-
leftRenderer.addActor(actor);
205-
const leftCamera = leftRenderer.getActiveCamera();
206-
leftCamera.set(cameraConfiguration);
207-
leftCamera.setWindowCenter(-eyeSpacing, -cameraCenterY);
208-
209-
rightRenderer.setViewport(0.5, 0, 1, 1);
210-
rightRenderer.addActor(actor);
211-
const rightCamera = rightRenderer.getActiveCamera();
212-
rightCamera.set(cameraConfiguration);
213-
rightCamera.setWindowCenter(eyeSpacing, -cameraCenterY);
214-
215-
// Provide custom update callback + fake camera
216-
updateCameraCallBack = () => {
217-
leftRenderer.resetCameraClippingRange();
218-
rightRenderer.resetCameraClippingRange();
219-
};
220-
camera = {
221-
setDeviceAngles(alpha, beta, gamma, screen) {
222-
leftCamera.setDeviceAngles(alpha, beta, gamma, screen);
223-
rightCamera.setDeviceAngles(alpha, beta, gamma, screen);
224-
},
225-
};
226-
227-
// Reconfigure render window
228-
renderWindow.addRenderer(leftRenderer);
229-
renderWindow.addRenderer(rightRenderer);
230-
renderWindow.removeRenderer(mainRenderer);
231-
232-
const distPass = vtkRadialDistortionPass.newInstance();
233-
distPass.setK1(distk1);
234-
distPass.setK2(distk2);
235-
distPass.setCameraCenterY(cameraCenterY);
236-
distPass.setCameraCenterX1(-eyeSpacing);
237-
distPass.setCameraCenterX2(eyeSpacing);
238-
distPass.setDelegates([vtkForwardPass.newInstance()]);
239-
fullScreenRenderer.getAPISpecificRenderWindow().setRenderPasses([distPass]);
240-
241-
// Hide any controller
242-
fullScreenRenderer.setControllerVisibility(false);
243-
244-
// Remove window interactions
245-
interactor.unbindEvents();
246-
247-
// Attach touch control
248-
if (!disableTouchNext) {
249-
fullScreenRenderer
250-
.getRootContainer()
251-
.addEventListener('touchstart', nextPosition, true);
252-
if (fullScreenMetod) {
253-
fullScreenRenderer.getRootContainer().addEventListener(
254-
'touchend',
255-
(e) => {
256-
body[fullScreenMetod]();
257-
},
258-
true
259-
);
260-
}
261-
}
262-
263-
// Warning if browser does not support fullscreen
264-
/* eslint-disable */
265-
if (navigator.userAgent.match('CriOS')) {
266-
alert(
267-
'Chrome on iOS does not support fullscreen. Please use Safari instead.'
268-
);
269-
}
270-
if (navigator.userAgent.match('FxiOS')) {
271-
alert(
272-
'Firefox on iOS does not support fullscreen. Please use Safari instead.'
273-
);
274-
}
275-
/* eslint-enable */
276-
} else {
277-
camera.set(cameraConfiguration);
278-
mainRenderer.addActor(actor);
279-
280-
// add vr option button if supported
281-
fullScreenRenderer.getApiSpecificRenderWindow().onHaveVRDisplay(() => {
282-
if (
283-
fullScreenRenderer.getApiSpecificRenderWindow().getVrDisplay()
284-
.capabilities.canPresent
285-
) {
286-
const button = document.createElement('button');
287-
button.style.position = 'absolute';
288-
button.style.left = '10px';
289-
button.style.bottom = '10px';
290-
button.style.zIndex = 10000;
182+
camera.set(cameraConfiguration);
183+
mainRenderer.addActor(actor);
184+
185+
// add vr option button if supported
186+
if (
187+
navigator.xr !== undefined &&
188+
navigator.xr.isSessionSupported('immersive-vr')
189+
) {
190+
const button = document.createElement('button');
191+
button.style.position = 'absolute';
192+
button.style.left = '10px';
193+
button.style.bottom = '10px';
194+
button.style.zIndex = 10000;
195+
button.textContent = 'Send To VR';
196+
document.querySelector('body').appendChild(button);
197+
button.addEventListener('click', () => {
198+
if (button.textContent === 'Send To VR') {
199+
fullScreenRenderer.getApiSpecificRenderWindow().startXR();
200+
button.textContent = 'Return From VR';
201+
} else {
202+
fullScreenRenderer.getApiSpecificRenderWindow().stopXR();
291203
button.textContent = 'Send To VR';
292-
document.querySelector('body').appendChild(button);
293-
button.addEventListener('click', () => {
294-
if (button.textContent === 'Send To VR') {
295-
fullScreenRenderer.getApiSpecificRenderWindow().startVR();
296-
button.textContent = 'Return From VR';
297-
} else {
298-
fullScreenRenderer.getApiSpecificRenderWindow().stopVR();
299-
button.textContent = 'Send To VR';
300-
}
301-
});
302204
}
303205
});
304206
}

Examples/Geometry/VR/index.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ const renderWindow = fullScreenRenderer.getRenderWindow();
3636
// this
3737
// ----------------------------------------------------------------------------
3838

39-
const coneSource = vtkConeSource.newInstance({ height: 100.0, radius: 50.0 });
40-
// const coneSource = vtkConeSource.newInstance({ height: 1.0, radius: 0.5 });
39+
const coneSource = vtkConeSource.newInstance({ height: 100.0, radius: 50 });
4140
const filter = vtkCalculator.newInstance();
4241

4342
filter.setInputConnection(coneSource.getOutputPort());
@@ -67,7 +66,7 @@ mapper.setInputConnection(filter.getOutputPort());
6766

6867
const actor = vtkActor.newInstance();
6968
actor.setMapper(mapper);
70-
actor.setPosition(20.0, 0.0, 0.0);
69+
actor.setPosition(0.0, 0.0, -20.0);
7170

7271
renderer.addActor(actor);
7372
renderer.resetCamera();
@@ -96,10 +95,10 @@ resolutionChange.addEventListener('input', (e) => {
9695

9796
vrbutton.addEventListener('click', (e) => {
9897
if (vrbutton.textContent === 'Send To VR') {
99-
fullScreenRenderer.getApiSpecificRenderWindow().startVR();
98+
fullScreenRenderer.getApiSpecificRenderWindow().startXR();
10099
vrbutton.textContent = 'Return From VR';
101100
} else {
102-
fullScreenRenderer.getApiSpecificRenderWindow().stopVR();
101+
fullScreenRenderer.getApiSpecificRenderWindow().stopXR();
103102
vrbutton.textContent = 'Send To VR';
104103
}
105104
});

Sources/Rendering/Core/RenderWindowInteractor/index.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ function vtkRenderWindowInteractor(publicAPI, model) {
366366
return;
367367
}
368368
animationRequesters.add(requestor);
369-
if (animationRequesters.size === 1) {
369+
if (animationRequesters.size === 1 && !model.xrAnimation) {
370370
model.lastFrameTime = 0.1;
371371
model.lastFrameStart = Date.now();
372372
model.animationRequest = requestAnimationFrame(publicAPI.handleAnimation);
@@ -375,7 +375,7 @@ function vtkRenderWindowInteractor(publicAPI, model) {
375375
};
376376

377377
publicAPI.isAnimating = () =>
378-
model.vrAnimation || model.animationRequest !== null;
378+
model.xrAnimation || model.animationRequest !== null;
379379

380380
publicAPI.cancelAnimation = (requestor, skipWarning = false) => {
381381
if (!animationRequesters.has(requestor)) {
@@ -398,17 +398,17 @@ function vtkRenderWindowInteractor(publicAPI, model) {
398398
}
399399
};
400400

401-
publicAPI.switchToVRAnimation = () => {
401+
publicAPI.switchToXRAnimation = () => {
402402
// cancel existing animation if any
403403
if (model.animationRequest) {
404404
cancelAnimationFrame(model.animationRequest);
405405
model.animationRequest = null;
406406
}
407-
model.vrAnimation = true;
407+
model.xrAnimation = true;
408408
};
409409

410-
publicAPI.returnFromVRAnimation = () => {
411-
model.vrAnimation = false;
410+
publicAPI.returnFromXRAnimation = () => {
411+
model.xrAnimation = false;
412412
if (animationRequesters.size !== 0) {
413413
model.FrameTime = -1;
414414
model.animationRequest = requestAnimationFrame(publicAPI.handleAnimation);
@@ -756,7 +756,7 @@ function vtkRenderWindowInteractor(publicAPI, model) {
756756
// do not want extra renders as the make the apparent interaction
757757
// rate slower.
758758
publicAPI.render = () => {
759-
if (model.animationRequest === null && !model.inRender) {
759+
if (!publicAPI.isAnimating() && !model.inRender) {
760760
forceRender();
761761
}
762762
};

0 commit comments

Comments
 (0)