<!DOCTYPE html> <meta name='viewport' content='width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'> <!-- three.js library --> <script src='../vendor/three.js/build/three.js'></script> <script src='../vendor/three.js/examples/js/libs/stats.min.js'></script> <!-- jsartookit --> <script src='../../vendor/jsartoolkit5/build/artoolkit.min.js'></script> <script src='../../vendor/jsartoolkit5/js/artoolkit.api.js'></script> <!-- include threex.artoolkit --> <script src='../../src/threex/threex-artoolkitsource.js'></script> <script src='../../src/threex/threex-artoolkitcontext.js'></script> <script src='../../src/threex/threex-artoolkitprofile.js'></script> <script src='../../src/threex/threex-arbasecontrols.js'></script> <script src='../../src/threex/threex-armarkercontrols.js'></script> <script src='../../src/threex/threex-armarkerhelper.js'></script> <script src='../../src/threex/threex-arsmoothedcontrols.js'></script> <script>THREEx.ArToolkitContext.baseURL = '../../'</script> <script src='../multi-markers/threex-armultimarkerutils.js'></script> <script src='../multi-markers/threex-armultimarkercontrols.js'></script> <script src='../multi-markers/threex-armultimarkerlearning.js'></script> <script src='js/threex-screenasportal.js'></script> <style> #recordButton:hover { cursor: pointer; } </style> <body style='margin : 0px; overflow: hidden; font-family: Monospace;'><div style='position: absolute; top: 10px; width:100%; text-align: center;z-index:1; color: grey;';> Screen as a gate to another world - by <a href='https://twitter.com/jerome_etienne' target='_blank'>@jerome_etienne</a> with <a href='https://github.com/jeromeetienne/AR.js/' target='_blank'>AR.js</a> <br> Directly inspired of the <a href='https://www.youtube.com/watch?v=Jd3-eiid-Uw'>cult demo</a> by <a href='https://www.youtube.com/user/jcl5m/videos'>johnny lee</a> </div> <div style='position: fixed; bottom: 10px; width:100%; text-align: center;z-index:1; color: grey;';> <a href='javascript:void(0)' onclick='toggleMarkerHelper()'>marker helper : <span id='markerHelpersStatus'></span></a> </div> <div style='position: fixed; bottom: 16px; right: 16px; z-index:1';> <img id='recordButton' src="../multi-markers/examples/images/record-start.png" width='64px' height='64px'> </div> <script> ;(function(){ //////////////////////////////////////////////////////////////////////////////// // handle urlOptions //////////////////////////////////////////////////////////////////////////////// // parse urlOptions from location.search if( location.search.substring(1) ){ var urlOptions = JSON.parse(decodeURIComponent(location.search.substring(1))) }else{ var urlOptions = {} } if( urlOptions.trackingBackend === undefined ) urlOptions.trackingBackend = 'artoolkit' ////////////////////////////////////////////////////////////////////////////////// // Init ////////////////////////////////////////////////////////////////////////////////// // init renderer var renderer = new THREE.WebGLRenderer({ alpha: true }); renderer.setClearColor(new THREE.Color('lightgrey'), 0) renderer.setSize( window.innerWidth, window.innerHeight ); renderer.domElement.style.position = 'absolute' renderer.domElement.style.top = '0px' renderer.domElement.style.left = '0px' document.body.appendChild( renderer.domElement ); // array of functions for the rendering loop var onRenderFcts= []; // init scene and camera var scene = new THREE.Scene(); ////////////////////////////////////////////////////////////////////////////////// // Initialize a basic camera ////////////////////////////////////////////////////////////////////////////////// // Create a camera if( urlOptions.trackingBackend === 'artoolkit' ){ var camera = new THREE.Camera(); }else console.assert(false) scene.add(camera); //////////////////////////////////////////////////////////////////////////////// // handle arToolkitSource //////////////////////////////////////////////////////////////////////////////// var artoolkitProfile = new THREEx.ArToolkitProfile() artoolkitProfile.sourceWebcam() var arToolkitSource = new THREEx.ArToolkitSource(artoolkitProfile.sourceParameters) arToolkitSource.init(function onReady(){ onResize() }) // handle resize window.addEventListener('resize', function(){ onResize() }) function onResize(){ arToolkitSource.onResize() arToolkitSource.copySizeTo(renderer.domElement) if( urlOptions.trackingBackend === 'artoolkit' ){ if( arToolkitContext.arController !== null ){ arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) } }else console.assert(false) } //////////////////////////////////////////////////////////////////////////////// // initialize arToolkitContext //////////////////////////////////////////////////////////////////////////////// // honor urlOptions.trackingBackend artoolkitProfile.contextParameters.trackingBackend = urlOptions.trackingBackend // create atToolkitContext var arToolkitContext = new THREEx.ArToolkitContext(artoolkitProfile.contextParameters) // initialize it arToolkitContext.init(function onCompleted(){ // if artoolkit, copy projection matrix to camera if( arToolkitContext.parameters.trackingBackend === 'artoolkit' ){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); } }) // update artoolkit on every frame onRenderFcts.push(function(){ if( arToolkitSource.ready === false ) return arToolkitContext.update( arToolkitSource.domElement ) }) ////////////////////////////////////////////////////////////////////////////// // init learnerParameters and markersControlsParameters ////////////////////////////////////////////////////////////////////////////// // build a multiMarkerControls var multiMarkerControls = THREEx.ArMultiMarkerControls.fromJSON(arToolkitContext, scene, markerRoot, multiMarkerFile) ////////////////////////////////////////////////////////////////////////////// // get multiMarkerFile ////////////////////////////////////////////////////////////////////////////// // if no localStorage.ARjsMultiMarkerFile, then write one with default marker if( localStorage.getItem('ARjsMultiMarkerFile') === null ){ THREEx.ArMultiMarkerControls.storeDefaultMultiMarkerFile(urlOptions.trackingBackend) } // get multiMarkerFile from localStorage console.assert( localStorage.getItem('ARjsMultiMarkerFile') !== null ) var multiMarkerFile = localStorage.getItem('ARjsMultiMarkerFile') ////////////////////////////////////////////////////////////////////////////// // Create ArMultiMarkerControls ////////////////////////////////////////////////////////////////////////////// // build a markerRoot var markerRoot = new THREE.Group() scene.add(markerRoot) // build a multiMarkerControls var multiMarkerControls = THREEx.ArMultiMarkerControls.fromJSON(arToolkitContext, scene, markerRoot, multiMarkerFile) // add an THREEx.ArMarkerHelper to visuable each sub-marker var markerHelpers = [] multiMarkerControls.subMarkersControls.forEach(function(subMarkerControls){ var markerHelper = new THREEx.ArMarkerHelper(subMarkerControls) subMarkerControls.object3d.add( markerHelper.object3d ) markerHelpers.push(markerHelper) }) // build a smoothedControls var smoothedRoot = new THREE.Group() scene.add(smoothedRoot) var smoothedControls = new THREEx.ArSmoothedControls(smoothedRoot) onRenderFcts.push(function(delta){ // parameters for updateSmoothedControls var lerpsValues = [ [0.1, 0.1, 0.5], [0.2, 0.1, 0.5], [0.2, 0.2, 0.5], [0.3, 0.2, 0.5], [0.3, 0.2, 0.5], ] // update smoothedControls parameters depending on how many markers are visible in multiMarkerControls multiMarkerControls.updateSmoothedControls(smoothedControls, lerpsValues) // update multiMarkerRoot position smoothedControls.update(markerRoot) }) var arWorldRoot = new THREE.Group() var averageMatrix = THREEx.ArMultiMarkerControls.computeCenter(multiMarkerFile) averageMatrix.decompose(arWorldRoot.position, arWorldRoot.quaternion, arWorldRoot.scale) smoothedRoot.add(arWorldRoot) ////////////////////////////////////////////////////////////////////////////// // toggle marker UI ////////////////////////////////////////////////////////////////////////////// document.querySelector('#recordButton').addEventListener('click', function(){ var learnerURL = THREEx.ArToolkitContext.baseURL + 'examples/multi-markers/examples/learner.html' THREEx.ArMultiMarkerUtils.navigateToLearnerPage(learnerURL, urlOptions.trackingBackend) }) window.toggleMarkerHelper = toggleMarkerHelper function toggleMarkerHelper(){ var wasVisible = markerHelpers[0].object3d.visible; document.querySelector('#markerHelpersStatus').innerHTML = wasVisible === false ? 'visible' : 'hidden' markerHelpers.forEach(function(markerHelper){ markerHelper.object3d.visible = wasVisible ? false : true }) } toggleMarkerHelper() ////////////////////////////////////////////////////////////////////////////////// // Add simple object on smoothedRoot ////////////////////////////////////////////////////////////////////////////////// ;(function(){ var screenAsPortal = new THREEx.ScreenAsPortal(multiMarkerFile) arWorldRoot.add(screenAsPortal.object3d) })() ////////////////////////////////////////////////////////////////////////////////// // render the whole thing on the page ////////////////////////////////////////////////////////////////////////////////// var stats = new Stats(); // document.body.appendChild( stats.dom ); // render the scene onRenderFcts.push(function(){ renderer.render( scene, camera ); stats.update(); }) // run the rendering loop var lastTimeMsec= null requestAnimationFrame(function animate(nowMsec){ // keep looping requestAnimationFrame( animate ); // measure time lastTimeMsec = lastTimeMsec || nowMsec-1000/60 var deltaMsec = Math.min(200, nowMsec - lastTimeMsec) lastTimeMsec = nowMsec // call each update function onRenderFcts.forEach(function(onRenderFct){ onRenderFct(deltaMsec/1000, nowMsec/1000) }) }) })() </script></body>