three.ar.js
Version:
A helper three.js library for building AR web experiences that run in WebARonARKit and WebARonARCore
239 lines (209 loc) • 6.97 kB
HTML
<!--
/*
* Copyright 2017 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<html lang="en">
<head>
<title>three.ar.js - Marker Detection</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000000;
margin: 0px;
overflow: hidden;
}
#info {
background-color: rgba(40, 40, 40, 0.4);
bottom: 0;
box-sizing: border-box;
color: rgba(255, 255, 255, 0.7);
left: 50%;
line-height: 1.3em;
padding: 0.75em;
position: absolute;
text-align: center;
transform: translate(-50%, 0);
width: 100%;
z-index: 10;
}
.divider {
color: rgba(255, 255, 255, 0.2);
padding: 0 0.5em;
}
#info a {
text-decoration: none;
color: white;
}
#dat {
user-select: none;
position: absolute;
left: 0;
top: 0;
z-Index: 200;
}
#glFullscreen {
width: 100%;
height: 100vh;
position: relative;
overflow: hidden;
z-index: 0;
}
a { color: skyblue }
</style>
</head>
<body>
<div id="info">
<a href="https://github.com/google-ar/three.ar.js">three.ar.js</a><span class="divider">|</span>Point device at a marker or QR code
</div>
<script src="../third_party/three.js/three.js"></script>
<script src="../third_party/three.js/VRControls.js"></script>
<script src="../third_party/dat.gui/dat.gui.js"></script>
<script src="../dist/three.ar.js"></script>
<script>
function GUI() {
this.markerTypeString = "AR";
this.markerType = 1;
return this;
}
// Global variables
var vrDisplay;
var vrControls;
var arView;
var canvas;
var camera;
var scene;
var renderer;
var stats;
var cameraOrtho, cameraScene, renderer, cameraMesh;
var vrDisplay = null;
var scene, cameraPersp, model = null;
var MODEL_SIZE_IN_METERS = 0.2;
var vrControls = null;
var gui;
var scale = new THREE.Vector3();
var MARKER_SIZE_IN_METERS = 0.06;
/**
* Use the `getARDisplay()` utility to leverage the WebVR API
* to see if there are any AR-capable WebVR VRDisplays. Returns
* a valid display if found. Otherwise, display the unsupported
* browser message.
*/
THREE.ARUtils.getARDisplay().then(function (display) {
if (display) {
if (display.getMarkers) {
vrDisplay = display;
init();
} else {
THREE.ARUtils.displayUnsupportedMessage("This prototype browser app for WebAR does not support marker detection yet.");
}
} else {
THREE.ARUtils.displayUnsupportedMessage();
}
});
function init() {
// Initialize the dat.GUI.
var datGUI = new dat.GUI();
gui = new GUI();
datGUI.add(gui, "markerTypeString", ["AR", "QRCODE"]).onFinishChange(function(value) {
if (!vrDisplay) {
return;
}
if (value === "QRCODE") {
gui.markerType = vrDisplay.MARKER_TYPE_QRCODE;
}
else if (value === "AR") {
gui.markerType = vrDisplay.MARKER_TYPE_AR;
}
}).name("Marker type");
// Setup the three.js rendering environment
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.autoClear = false;
canvas = renderer.domElement;
document.body.appendChild(canvas);
scene = new THREE.Scene();
// Creating the ARView, which is the object that handles
// the rendering of the camera stream behind the three.js
// scene
arView = new THREE.ARView(vrDisplay, renderer);
// The ARPerspectiveCamera is very similar to THREE.PerspectiveCamera,
// except when using an AR-capable browser, the camera uses
// the projection matrix provided from the device, so that the
// perspective camera's depth planes and field of view matches
// the physical camera on the device.
camera = new THREE.ARPerspectiveCamera(vrDisplay, 60, window.innerWidth / window.innerHeight, 0.01, 100);
// Create a model to be placed in the world using picking
model = new THREE.Mesh(new THREE.ConeBufferGeometry(
MODEL_SIZE_IN_METERS / 2, MODEL_SIZE_IN_METERS),
new THREE.MeshLambertMaterial( {color: 0x888888 } ));
// Apply a rotation to the model so it faces in the direction of the
// normal of the plane when the picking based reorientation is done
model.geometry.applyMatrix(
new THREE.Matrix4().makeTranslation(0, MODEL_SIZE_IN_METERS / 2, 0));
model.geometry.applyMatrix(
new THREE.Matrix4().makeRotationX(THREE.Math.degToRad(90)));
model.position.set(0, 0, -1);
scene.add(model);
// Add some lighting
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(0, 1, 0);
scene.add(directionalLight);
// VRControls is a utility from three.js that applies the device's
// orientation/position to the perspective camera, keeping our
// real world and virtual world in sync.
vrControls = new THREE.VRControls(camera);
// Correctly handle window resize events
window.addEventListener( 'resize', onWindowResize, false );
update();
}
/**
* On window resize, update the perspective camera's aspect ratio,
* and call `updateProjectionMatrix` so that we can get the latest
* projection matrix provided from the device
*/
function onWindowResize () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function update() {
// Render the device's camera stream on screen first of all.
// It allows to get the right pose synchronized with the right frame.
arView.render();
// Update our camera projection matrix in the event that
// the near or far planes have updated
camera.updateProjectionMatrix();
// Update our perspective camera's positioning
vrControls.update();
// Render our three.js virtual scene
renderer.clearDepth();
renderer.render(scene, camera);
var markers = vrDisplay.getMarkers(gui.markerType, MARKER_SIZE_IN_METERS);
if (markers.length > 0) {
model.matrix.fromArray(markers[0].modelMatrix);
model.matrix.decompose(model.position, model.quaternion, scale);
}
// Kick off the requestAnimationFrame to call this function
// when a new VRDisplay frame is rendered
vrDisplay.requestAnimationFrame(update);
}
</script>
</body>
</html>