Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds explanation to readme of how to use the javascript library #38

Merged
merged 3 commits into from
Feb 26, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
103 changes: 103 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,109 @@ Certain WebVR `Gamepad` objects have some components with an inverted `yAxis` ca
}
```

# Source Library
This repo provides a javascript library for interpreting the `mapping.json` files and binding them to a live `Gamepad` object. Developers can uses this library to interact with the conceptual components of the gamepad, rather than each individual button or axis.

## Connection and Disconnection
In order to use this library, developers create a new `XRGamepad` by passing it the associated mapping file, the live `Gamepad` object, and an indication of which `handedness` should be applied. The initialization path for a WebXR gamepad is slightly different than for a WebVR gamepad for several reasons. First, newly connected gamepads are reported in WebXR through the `XRSession.inputsourceschange` event where as in WebVR they are reported through the `navigator.gamepadconnected` event. Second, the handedness is passed separately due to the fact that in WebXR handedness is a property of the `XRInputSource`, whereas in WebVR handedness is a property of the `Gamepad`.

### WebXR Connection and Disconnection
This sample code shows creating an `XRGamepad` based on the `XRInputSource.gamepad` property for all newly connected `XRInputSource` objects. When an `XRInputSource` is disconnected the `XRGamepad` is released.

```js
let xrGamepads = {};
xrSession.addEventListener('inputsourceschange', onInputSourcesChange);

function onInputSourcesChange(event) {
event.added.forEach((inputSource) => {
if (inputSource.gamepad) {
let mapping = XRGamepad.getMapping(gamepad.id, XRMappingConstants.MappingType.WebXR);
let xrGamepad = new XRGamepad(gamepad, mapping, inputSource.handedness);
xrGamepads[inputSource] = xrGamepad;
}
}

event.removed.forEach((inputSource) => {
if (xrGamepads[inputSource]) {
delete xrGamepads[inputSource];
}
});
}
```

### WebVR Connection and Disconnection
This sample code shows creating an `XRGamepad` for all newly connected `Gamepad` objects associated with WebVR. When an associated `Gamepad` is disconnected the `XRGamepad` is released.

```js
let xrGamepads = {};
navigator.addEventListener('gamepadconnected', onGamepadConnected);
navigator.addEventListener('gamepaddisconnected', onGamepadDisconnected);

function onGamepadConnected(event) {
let gamepad = event.gamepad;
if (gamepad.deviceId) {
let mapping = XRGamepad.getMapping(gamepad.id, XRMappingConstants.MappingType.WebVR);
let xrGamepad = new XRGamepad(gamepad, mapping, gamepad.handedness);
xrGamepads[gamepad] = xrGamepad;
}
}

function onGamepadDisconnected(event) {
if (xrGamepads[event.gamepad]) {
delete xrGamepads[event.gamepad];
}
}
}
```

## Engine Loop
On each frame, the gamepad data must be requeried and the engine must respond accordingly to the new data. This will be the same for both WebXR and WebVR

```js
function updateGamepads() {
Object.key(xrGamepads).forEach((key) => {
let xrGamepad = xrGamepads[key];
xrGamepads.components.forEach((xrComponent) => {
const xrComponentData = xrComponent.getData();
MyEngine.respondToInput(key, xrComponentData);

const weightedVisualizations = xrComponent.getWeightedVisualizations();
MyEngine.updateInputVisuals(key, weightedVisualizations);
});
});
}
```

> TODO Add an explanation for how to updated the visuals based on the weighted visualizations

## Target Ray Origin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is feedback that's a couple of PRs too late, but it didn't really click with me till I saw it used in context. The use of "origin" here feels to me like it only implies a position offset, so it read kind of weird to me at first. Is there a better term that we could use?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to whatever, though I'd like to not hold this PR for it...

In WebXR and WebVR a target ray may be drawn for motion controllers, however the origin of this ray is retrieved differently for each.

### WebXR Target Ray Origin
In WebXR, the `XRInputSource.targetRaySpace` should be passed into `XRFrame.getPose()` to determined the pointing origin.

```js
function getTargetRayOrigin(xrFrame, xrInputSource) {
return xrFrame.getPose(xrInputSource.targetRaySpace, xrReferenceSpace);
}
```

### WebVR Target Ray Origin
In WebVR there is no implicit mechanism for retrieving a target ray origin. Instead, it must be retrieved from the the mapping via the `XRGamepad` and multiplied by the `Gamepad` object's pose in matrix form.
```js
function getTargetRayOrigin(xrGamepad){
let targetRayOrigin;

const gamepadPose = xrGamepad.gamepad.gamepadPose;
if (gamepadPose && gamepadPose.hasOrientation && gamepadPose.hasPosition) {
const gamepadPoseMatrix = new MyMatrixMathLibrary.RigidTransform(gamepadPose.position, gamepadPose.orientation);
targetRayOrigin = MyMatrixMathLibrary.Multiply(gamepadPoseMatrix, xrGamepad.targetRayOrigin);
}

return targetRayOrigin;
}
```

# Appendices

## Licence
Expand Down
4 changes: 4 additions & 0 deletions src/xrGamepad.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ class XRGamepad {
return this.hand.root;
}

get targetRayOrigin() {
return this.hand.targetRayOrigin;
}

/**
* @description Gets the mapping description for the supplied gamepad id
* @param {String} gamepadId The id of the Gamepad to find the mapping for
Expand Down