UNPKG

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
<!-- /* * 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. */ --> <!DOCTYPE html> <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>