Skip to content

Commit

Permalink
WebXR Support (#1834)
Browse files Browse the repository at this point in the history
* origin/webxr

* lint fixes

* respect parent transform, fix start/end session rendering

* resize graphics device to respect XR session framebuffer

* provide multiple XR session types; AR

* better API, tidy up, lint clean

* jsdocs fixes

* fix tests

* add backwards compatibility warnings for VR

* remove deprecated VR camera logic

* remove VR examples and add XR examples

* lint errors

* address PR comments

* calculate camera XR frustum based on XR view

* fix XR normals bug, and change position/rotation calculation

* API renaming/simplification

* undepricate WebVR

* fixes

* rename pc.XR_TYPE_* to simplified version

* remove CameraComponent.isXr property

Co-authored-by: Will Eastcott <will@playcanvas.com>
  • Loading branch information
Maksims and willeastcott committed Feb 8, 2020
1 parent 5f7c501 commit 64410ef
Show file tree
Hide file tree
Showing 13 changed files with 1,070 additions and 91 deletions.
1 change: 1 addition & 0 deletions build/dependencies.txt
Expand Up @@ -111,6 +111,7 @@
../src/input/element-input.js
../src/vr/vr-manager.js
../src/vr/vr-display.js
../src/xr/xr-manager.js
../src/net/http.js
../src/script/script-registry.js
../src/script/script.js
Expand Down
8 changes: 7 additions & 1 deletion examples/examples.js
Expand Up @@ -71,5 +71,11 @@ var categories = [
"text-wrap",
"various"
]
}, {
name: "xr",
examples: [
'augmented-reality-basic',
'virtual-reality-basic'
]
}
];
];
85 changes: 52 additions & 33 deletions examples/style.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions examples/style.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions examples/style.scss
Expand Up @@ -48,7 +48,7 @@ body {
}
}
}

.sidenav-toggle {
position: absolute;
right: 12px;
Expand Down Expand Up @@ -108,8 +108,8 @@ iframe {
border: 0px;
left: 0;
right: 0;
padding-left: 160px;
width: calc(100% - 160px);
padding-left: 240px;
width: calc(100% - 240px);
height: 100%;
overflow: auto;
@media screen and (max-width: $break-medium) {
Expand Down
170 changes: 170 additions & 0 deletions examples/xr/augmented-reality-basic.html
@@ -0,0 +1,170 @@
<!DOCTYPE html>
<html>
<head>
<title>PlayCanvas Virtual 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" />
<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(0, 0, 0, 0),
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",
});
cube.setLocalScale(.5, .5, .5);
cube.translate(x * .5, y, z * .5);
app.root.addChild(cube);
};

// 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, 2*y - SIZE);
}
}

if (app.xr.supported) {
var activate = function () {
if (app.xr.isAvailable(pc.XR_TYPE_IMMERSIVE_AR)) {
c.camera.startXr(pc.XR_TYPE_IMMERSIVE_AR, function (err) {
if (err) message("WebXR Immersive AR failed to start: " + err.message);
});
} else {
message("WebXR Immersive AR 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();
}
});

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

if (! app.xr.isAvailable(pc.XR_TYPE_IMMERSIVE_AR)) {
message("WebXR Immersive AR is not available");
}
} else {
message("WebXR is not supported");
}
</script>
</body>
</html>

0 comments on commit 64410ef

Please sign in to comment.