Skip to content

Commit ce66ef1

Browse files
committed
feat(XR): Remap OpenVR gamepad for OpenXR gamepad support
1 parent 71fa4cd commit ce66ef1

File tree

4 files changed

+55
-29
lines changed

4 files changed

+55
-29
lines changed

Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) {
5858
ed &&
5959
ed.pressed &&
6060
ed.device === Device.RightController &&
61-
ed.input === Input.TrackPad
61+
(ed.input === Input.Trigger || ed.input === Input.TrackPad)
6262
) {
6363
publicAPI.startCameraPose();
6464
return;
@@ -67,7 +67,7 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) {
6767
ed &&
6868
!ed.pressed &&
6969
ed.device === Device.RightController &&
70-
ed.input === Input.TrackPad &&
70+
(ed.input === Input.Trigger || ed.input === Input.TrackPad) &&
7171
model.state === States.IS_CAMERA_POSE
7272
) {
7373
publicAPI.endCameraPose();
@@ -91,13 +91,18 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) {
9191
const oldTrans = camera.getPhysicalTranslation();
9292

9393
// look at the y axis to determine how fast / what direction to move
94-
const speed = ed.gamepad.axes[1];
94+
const speed = 0.5; // ed.gamepad.axes[1];
9595

9696
// 0.05 meters / frame movement
9797
const pscale = speed * 0.05 * camera.getPhysicalScale();
9898

9999
// convert orientation to world coordinate direction
100-
const dir = camera.physicalOrientationToWorldDirection(ed.orientation);
100+
const dir = camera.physicalOrientationToWorldDirection([
101+
ed.orientation.x,
102+
ed.orientation.y,
103+
ed.orientation.z,
104+
ed.orientation.w,
105+
]);
101106

102107
camera.setPhysicalTranslation(
103108
oldTrans[0] + dir[0] * pscale,

Sources/Rendering/Core/RenderWindowInteractor/Constants.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,22 @@ export const Input = {
99
Trigger: 1,
1010
TrackPad: 2,
1111
Grip: 3,
12-
ApplicationMenu: 4,
12+
Thumbstick: 4,
13+
A: 5,
14+
B: 6,
15+
ApplicationMenu: 7, // Not exposed in WebXR API
16+
};
17+
18+
export const Axis = {
19+
Unknown: 0,
20+
TouchpadX: 1,
21+
TouchpadY: 2,
22+
ThumbstickX: 3,
23+
ThumbstickY: 4,
1324
};
1425

1526
export default {
1627
Device,
1728
Input,
29+
Axis,
1830
};

Sources/Rendering/Core/RenderWindowInteractor/index.js

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ const { vtkWarningMacro, vtkErrorMacro, normalizeWheel, vtkOnceErrorMacro } =
1212
// ----------------------------------------------------------------------------
1313

1414
const deviceInputMap = {
15-
'OpenVR Gamepad': [
16-
Input.TrackPad,
15+
'xr-standard': [
1716
Input.Trigger,
1817
Input.Grip,
19-
Input.ApplicationMenu,
18+
Input.TrackPad,
19+
Input.Thumbstick,
20+
Input.A,
21+
Input.B,
2022
],
2123
};
2224

@@ -415,55 +417,58 @@ function vtkRenderWindowInteractor(publicAPI, model) {
415417
}
416418
};
417419

418-
publicAPI.updateGamepads = (displayId) => {
419-
const gamepads = navigator.getGamepads();
420-
420+
publicAPI.updateXRGamepads = (xrSession, xrFrame, xrRefSpace) => {
421421
// watch for when buttons change state and fire events
422-
for (let i = 0; i < gamepads.length; ++i) {
423-
const gp = gamepads[i];
424-
if (gp && gp.displayId === displayId) {
422+
xrSession.inputSources.forEach((inputSource) => {
423+
const pose = xrFrame.getPose(inputSource.gripSpace, xrRefSpace);
424+
const gp = inputSource.gamepad;
425+
const hand = inputSource.handedness;
426+
if (gp) {
425427
if (!(gp.index in model.lastGamepadValues)) {
426-
model.lastGamepadValues[gp.index] = { buttons: {} };
428+
model.lastGamepadValues[gp.index] = {
429+
left: { buttons: {} },
430+
right: { buttons: {} },
431+
};
427432
}
428433
for (let b = 0; b < gp.buttons.length; ++b) {
429-
if (!(b in model.lastGamepadValues[gp.index].buttons)) {
430-
model.lastGamepadValues[gp.index].buttons[b] = false;
434+
if (!(b in model.lastGamepadValues[gp.index][hand].buttons)) {
435+
model.lastGamepadValues[gp.index][hand].buttons[b] = false;
431436
}
432437
if (
433-
model.lastGamepadValues[gp.index].buttons[b] !==
438+
model.lastGamepadValues[gp.index][hand].buttons[b] !==
434439
gp.buttons[b].pressed
435440
) {
436441
publicAPI.button3DEvent({
437442
gamepad: gp,
438-
position: gp.pose.position,
439-
orientation: gp.pose.orientation,
443+
position: pose.transform.position,
444+
orientation: pose.transform.orientation,
440445
pressed: gp.buttons[b].pressed,
441446
device:
442-
gp.hand === 'left'
447+
inputSource.handedness === 'left'
443448
? Device.LeftController
444449
: Device.RightController,
445450
input:
446-
deviceInputMap[gp.id] && deviceInputMap[gp.id][b]
447-
? deviceInputMap[gp.id][b]
451+
deviceInputMap[gp.mapping] && deviceInputMap[gp.mapping][b]
452+
? deviceInputMap[gp.mapping][b]
448453
: Input.Trigger,
449454
});
450-
model.lastGamepadValues[gp.index].buttons[b] =
455+
model.lastGamepadValues[gp.index][hand].buttons[b] =
451456
gp.buttons[b].pressed;
452457
}
453-
if (model.lastGamepadValues[gp.index].buttons[b]) {
458+
if (model.lastGamepadValues[gp.index][hand].buttons[b]) {
454459
publicAPI.move3DEvent({
455460
gamepad: gp,
456-
position: gp.pose.position,
457-
orientation: gp.pose.orientation,
461+
position: pose.transform.position,
462+
orientation: pose.transform.orientation,
458463
device:
459-
gp.hand === 'left'
464+
inputSource.handedness === 'left'
460465
? Device.LeftController
461466
: Device.RightController,
462467
});
463468
}
464469
}
465470
}
466-
}
471+
});
467472
};
468473

469474
publicAPI.handleMouseMove = (event) => {

Sources/Rendering/OpenGL/RenderWindow/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
354354
publicAPI.xrRender = async (t, frame) => {
355355
const xrSession = frame.session;
356356

357+
model.renderable
358+
.getInteractor()
359+
.updateXRGamepads(xrSession, frame, model.xrReferenceSpace);
360+
357361
model.xrSceneFrame = model.xrSession.requestAnimationFrame(
358362
publicAPI.xrRender
359363
);

0 commit comments

Comments
 (0)