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

WebXR Input Sources #1873

Merged
merged 23 commits into from
Feb 21, 2020
Merged

Conversation

Maksims
Copy link
Collaborator

@Maksims Maksims commented Feb 13, 2020

This PR adds WebXR Input Sources, which provides interface to various input methods in VR and AR environments.

It is WIP PR, so comments and ideas are welcome.

New APIs:

app.xr.input // instance of pc.XrInput

// pc.XrInput
app.xr.input.inputSources // list of active input sources
app.xr.input.on('add', function(inputSource) { }); // event when pc.XrInputSource is added
app.xr.input.on('remove', function(inputSource) { }); // event when pc.XrInputSource is removed
app.xr.input.on('select', function(inputSource, evt) { }); // when device is triggered. This could be handheld main trigger button, or screen tap on mobile
app.xr.input.on('selectstart', function(inputSource, evt) { }); // when devices starts to be triggered
app.xr.input.on('selectend', function(inputSource, evt) { }); // when devices ends trigger

// pc.XrInputSource
inputSource.ray // pc.Ray in XR session space, origin and direction of the pointing device
inputSource.grip // True if input source can be held
inputSource.position // pc.Vec3 | null - position of handheld device in XR session space
inputSource.rotation // pc.Quat | null - rotation of handheld device in XR session space
inputSource.selecting // True if input source is in primary action state, such as trigger button is pressed or screen is being touched.
inputSource.gamepad // null or instance of Gamepad. This is available on platforms with support of https://www.w3.org/TR/webxr-gamepads-module-1/
inputSource.targetRayMode // string, one of pc.XRTARGETRAY_*
inputSource.handedness // string, one of pc.XRHAND_*
inputSource.profiles // array of strings, lists of profiles reported by device of its visual and behavioural representation. Refer to official documentation: https://www.w3.org/TR/webxr/#dom-xrinputsource-profiles
inputSource.inputSource // XRInputSource - raw object from WebXR
inputSource.on('remove', function() { }); // when device is removed/disconnected
inputSource.on('select', function(evt) { }); // when device is triggered. This could be handheld main trigger button, or screen tap on mobile
inputSource.on('selectstart', function(evt) { }); // when devices starts to be triggered
inputSource.on('selectend', function(evt) { }); // when device ends trigger

// pc
pc.XRTARGETRAY_GAZE // 'gaze' - indicates the target ray will originate at the viewer and follow the direction it is facing. (This is commonly referred to as a "gaze input" device in the context of head-mounted displays.)
pc.XRTARGETRAY_SCREEN // 'screen' - indicates that the input source was an interaction with the canvas element associated with an inline session’s output context, such as a mouse click or touch event.
pc.XRTARGETRAY_POINTER // 'tracked-pointer' - indicates that the target ray originates from either a handheld device or other hand-tracking mechanism and represents that the user is using their hands or the held device for pointing.

pc.XRHAND_NONE // 'none' - input source is not meant to be held in hands.
pc.XRHAND_LEFT // 'left' - indicates that input source is meant to be held in left hand.
pc.XRHAND_RIGHT // 'right' - indicates that input source is meant to be held in right hand.

I confirm I have signed the Contributor License Agreement.

@Maksims
Copy link
Collaborator Author

Maksims commented Feb 13, 2020

Here is basic example, that provides simple entity picking by bounding box, that works with multi-controllers (Oculus Quest for example); gaze (mobile devices); screen (AR taps on screens).

select.js (attach on entity with model):

var Select = pc.createScript('select');

Select.prototype.initialize = function() {

    // when select is triggered
    this.app.xr.input.on('select', function(inputSource) {

        // get mesh of this entity
        var mesh = this.entity.model.meshInstances[0];

        // check if input source ray intersects with mesh bounding box
        if (mesh.aabb.intersectsRay(inputSource.ray)) {

            // randomize its diffuse color
            mesh.material.diffuse.set(Math.random(), Math.random(), Math.random());
            mesh.material.update();
        }
    }, this);
};

@Maksims
Copy link
Collaborator Author

Maksims commented Feb 13, 2020

Here is basic example for adding/removing input sources and positioning entity based on grip position and rotation of a physical controller.

controllers.js: (somewhere on root)

var Controllers = pc.createScript('controllers');

// entity for controller template
Controllers.attributes.add('template', {
    type: 'entity'
});

Controllers.prototype.initialize = function() {
    // when input source added
    this.app.xr.input.on('add', function(inputSource) {
        var entity = this.template.clone();
        entity.script.controller.inputSource = inputSource;
        entity.reparent(this.app.scene.root);
        entity.enabled = true;
    }, this);
};

controller.js: (on controller entity)

var Controller = pc.createScript('controller');

Controller.attributes.add('inputSource', { type: 'string' });

Controller.prototype.initialize = function() {
    this.inputSource.on('remove', function() {
        // destroy self when input source is removed
        this.entity.destroy();
    }, this);
};

Controller.prototype.update = function(dt) {
    if (this.inputSource.grip) {
        // if can be gripped
        this.entity.model.enabled = true;
        this.entity.setLocalPosition(this.inputSource.position);
        this.entity.setLocalRotation(this.inputSource.rotation);
    } else {
        // some controllers cannot be gripped
        this.entity.model.enabled = false;
    }
};

@Maksims Maksims marked this pull request as ready for review February 20, 2020 23:15
@willeastcott willeastcott merged commit bbac2f9 into playcanvas:master Feb 21, 2020
TheJonRobinson added a commit to Mojiworks/playcanvas-engine that referenced this pull request Feb 23, 2020
* master: (31 commits)
  WebXR Input Sources (playcanvas#1873)
  Simplified constants definition in Math classes (playcanvas#1876)
  Improve batching to handle 8-bit and 32-bit index buffers (playcanvas#1872)
  Add particle start frame example to browser
  [FIX] Update WebXR examples to use latest enums (playcanvas#1870)
  [FIX] Add XRWebGLLayer to externs for Closure compiler (playcanvas#1869)
  update paths in the particle system start frame example (playcanvas#1868)
  add a animation start frame variable to the particle system which def… (playcanvas#1864)
  point cloud example using engine directly, and custom shader changing size and color of points (playcanvas#1867)
  WebXR Support (playcanvas#1834)
  Hardware Instancing fixes / sample (playcanvas#1846) (playcanvas#1856)
  [VERSION] v1.25.0-dev
  [RELEASE] v1.24.7
  Recompiled basis, now works on IE (playcanvas#1865)
  Small mesh cleanup (playcanvas#1866)
  [FIX] Revert memory-leak change (playcanvas#1862)
  [FIX] Flag model as immutable when it's added to a ModelComponent (playcanvas#1861)
  [FIX] Fix calculation of deprecated pc.MouseEvent#wheel (playcanvas#1859)
  [DOCS] Adjust Vec3.normalize docs to reflect behavior better (playcanvas#1849)
  pc.BatchManager.markGroupDirty is now public (playcanvas#1848)
  ...
@Maksims Maksims deleted the webxr-inputsources branch April 4, 2020 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants