Skip to content

Commit

Permalink
WebXR Input Sources (#1873)
Browse files Browse the repository at this point in the history
* initial work in progress for webxr input sources

* initial XR input sources PR

* added WebXR Input Sources constants

* fix

* document WebXR Input Sources

* fix lint and build issues

* fix typo

* add xr-picking example

* add vr controller example

* make XR controllers in XR local space

* updated XR examples, added VR Movement example

* add space type to start XR session

* lint fixes

* Doc tweaks.

* Spelling correction

* Doc tweaks

* curently -> currently

* Docs tweaks

Co-authored-by: Will Eastcott <[email protected]>
  • Loading branch information
Maksims and willeastcott authored Feb 21, 2020
1 parent cb2f443 commit bbac2f9
Show file tree
Hide file tree
Showing 12 changed files with 1,307 additions and 70 deletions.
2 changes: 2 additions & 0 deletions build/dependencies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@
../src/vr/vr-manager.js
../src/vr/vr-display.js
../src/xr/xr-manager.js
../src/xr/xr-input.js
../src/xr/xr-input-source.js
../src/net/http.js
../src/script/script-registry.js
../src/script/script.js
Expand Down
5 changes: 4 additions & 1 deletion examples/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ var categories = [
name: "xr",
examples: [
'augmented-reality-basic',
'virtual-reality-basic'
'virtual-reality-basic',
'xr-picking',
'vr-controllers',
'vr-movement'
]
}
];
14 changes: 7 additions & 7 deletions examples/xr/augmented-reality-basic.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>PlayCanvas Virtual Reality</title>
<title>PlayCanvas Augmented Reality</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="icon" type="image/png" href="../playcanvas-favicon.png" />
Expand Down Expand Up @@ -117,11 +117,11 @@
if (app.xr.supported) {
var activate = function () {
if (app.xr.isAvailable(pc.XRTYPE_AR)) {
c.camera.startXr(pc.XRTYPE_AR, function (err) {
c.camera.startXr(pc.XRTYPE_AR, pc.XRSPACE_VIEWER, function (err) {
if (err) message("WebXR Immersive AR failed to start: " + err.message);
});
} else {
message("WebXR Immersive AR is not available");
message("Immersive AR is not available");
}
};

Expand Down Expand Up @@ -150,17 +150,17 @@
});

app.xr.on('start', function () {
message("WebXR Immersive AR session has started");
message("Immersive AR session has started");
});
app.xr.on('end', function () {
message("WebXR Immersive AR session has ended");
message("Immersive AR session has ended");
});
app.xr.on('available:' + pc.XRTYPE_AR, function (available) {
message("WebXR Immersive AR is now " + (available ? 'available' : 'unavailable'));
message("Immersive AR is " + (available ? 'available' : 'unavailable'));
});

if (! app.xr.isAvailable(pc.XRTYPE_AR)) {
message("WebXR Immersive AR is not available");
message("Immersive AR is not available");
}
} else {
message("WebXR is not supported");
Expand Down
17 changes: 10 additions & 7 deletions examples/xr/virtual-reality-basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@
if (app.xr.supported) {
var activate = function () {
if (app.xr.isAvailable(pc.XRTYPE_VR)) {
c.camera.startXr(pc.XRTYPE_VR, function (err) {
c.camera.startXr(pc.XRTYPE_VR, pc.XRSPACE_LOCAL, function (err) {
if (err) message("WebXR Immersive VR failed to start: " + err.message);
});
} else {
message("WebXR Immersive VR is not available");
message("Immersive VR is not available");
}
};

Expand All @@ -131,14 +131,17 @@
});

if (app.touch) {
app.touch.on("touchend", function () {
app.touch.on("touchend", function (evt) {
if (! app.xr.active) {
// if not in VR, activate
activate();
} else {
// otherwise reset camera
c.camera.endXr();
}

evt.preventDefault();
evt.stopPropagation();
});
}

Expand All @@ -150,17 +153,17 @@
});

app.xr.on('start', function () {
message("WebXR Immersive VR session has started");
message("Immersive VR session has started");
});
app.xr.on('end', function () {
message("WebXR Immersive VR session has ended");
message("Immersive VR session has ended");
});
app.xr.on('available:' + pc.XRTYPE_VR, function (available) {
message("WebXR Immersive VR is now " + (available ? 'available' : 'unavailable'));
message("Immersive VR is " + (available ? 'available' : 'unavailable'));
});

if (! app.xr.isAvailable(pc.XRTYPE_VR)) {
message("WebXR Immersive VR is not available");
message("Immersive VR is not available");
}
} else {
message("WebXR is not supported");
Expand Down
200 changes: 200 additions & 0 deletions examples/xr/vr-controllers.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
<!DOCTYPE html>
<html>
<head>
<title>PlayCanvas VR Controllers</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="icon" type="image/png" href="../playcanvas-favicon.png" />
<script src="../../build/output/playcanvas.js"></script>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
}
canvas {
width:100%;
height:100%;

}
.message {
position: absolute;
padding: 8px 16px;
left: 20px;
bottom: 0px;
color: #ccc;
background-color: rgba(0, 0, 0, .5);
font-family: "Proxima Nova", Arial, sans-serif;
}
</style>
</head>

<body>
<canvas id="application-canvas"></canvas>
<div>
<p class="message"></p>
</div>
<script>
// draw some axes
var drawAxes = function (pos, scale) {
var color = new pc.Color(1,0,0);

var axis = new pc.Vec3();
var end = new pc.Vec3().copy(pos).add(axis.set(scale,0,0));

app.renderLine(pos, end, color);

color.set(0, 1, 0);
end.sub(axis.set(scale,0,0)).add(axis.set(0,scale,0));
app.renderLine(pos, end, color);

color.set(0, 0, 1);
end.sub(axis.set(0,scale,0)).add(axis.set(0,0,scale));
app.renderLine(pos, end, color);
}
</script>


<script>
var message = function (msg) {
var el = document.querySelector('.message');
el.textContent = msg;
}

var canvas = document.getElementById('application-canvas');
var app = new pc.Application(canvas, {
mouse: new pc.Mouse(canvas),
touch: new pc.TouchDevice(canvas),
keyboard: new pc.Keyboard(window)
});
app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
app.setCanvasResolution(pc.RESOLUTION_AUTO);

window.addEventListener("resize", function () {
app.resizeCanvas(canvas.width, canvas.height);
});

// use device pixel ratio
app.graphicsDevice.maxPixelRatio = window.devicePixelRatio;

app.start();

// create camera
var c = new pc.Entity();
c.addComponent('camera', {
clearColor: new pc.Color(44/255, 62/255, 80/255),
farClip: 10000
});
app.root.addChild(c);

var l = new pc.Entity();
l.addComponent("light", {
type: "spot",
range: 30
});
l.translate(0,10,0);
app.root.addChild(l);

var createCube = function(x,y,z) {
var cube = new pc.Entity();
cube.addComponent("model", {
type: "box",
material: new pc.StandardMaterial()
});
cube.setLocalScale(1,1,1);
cube.translate(x, y, z);
app.root.addChild(cube);
};

var controllers = [ ];
// create controller box
var createController = function(inputSource) {
var entity = new pc.Entity();
entity.addComponent('model', {
type: 'box'
});
entity.setLocalScale(0.05, 0.05, 0.05);
app.root.addChild(entity);
entity.inputSource = inputSource;
controllers.push(entity);

// destroy input source related entity
// when input source is removed
inputSource.on('remove', function() {
controllers.splice(controllers.indexOf(entity), 1);
entity.destroy();
});
};

// create a grid of cubes
var SIZE = 4;
for (var x = 0; x <= SIZE; x++) {
for (var y = 0; y <= SIZE; y++) {
createCube(2*x - SIZE, -1.5, 2*y - SIZE);
}
}

if (app.xr.supported) {
var activate = function () {
if (app.xr.isAvailable(pc.XRTYPE_VR)) {
c.camera.startXr(pc.XRTYPE_VR, pc.XRSPACE_LOCAL, function (err) {
if (err) message("Immersive VR failed to start: " + err.message);
});
} else {
message("Immersive VR is not available");
}
};

app.mouse.on("mousedown", function () {
if (! app.xr.active)
activate();
});

if (app.touch) {
app.touch.on("touchend", function () {
if (! app.xr.active) {
// if not in VR, activate
activate();
} else {
// otherwise reset camera
c.camera.endXr();
}
});
}

// end session by keyboard ESC
app.keyboard.on('keydown', function (evt) {
if (evt.key === pc.KEY_ESCAPE && app.xr.active) {
app.xr.end();
}
});

// when new input source added
app.xr.input.on('add', function(inputSource) {
message("Controller Added");
createController(inputSource);
});

message("Tap on screen to enter VR, and see controllers");

// update position and rotation for each controller
app.on('update', function() {
for(var i = 0; i < controllers.length; i++) {
var inputSource = controllers[i].inputSource;
if (inputSource.grip) {
// some controllers can be gripped
controllers[i].enabled = true;
controllers[i].setPosition(inputSource.position);
controllers[i].setRotation(inputSource.rotation);
} else {
// some controllers cannot be gripped
controllers[i].enabled = false;
}
}
});
} else {
message("WebXR is not supported");
}
</script>
</body>
</html>
Loading

0 comments on commit bbac2f9

Please sign in to comment.