<!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> <!-- ar.js --> <script src="../build/ar-threex.js"></script> <script>THREEx.ArToolkitContext.baseURL = '../'</script> <!-- Bind window error for error handling --> <script> window.addEventListener('error', function (event) { alert("ERROR: " + event.message + " at " + event.filename + " : " + event.lineno + " : " + event.colno); }); </script> <body style='margin : 0px; overflow: hidden; font-family: Monospace;'> <div style='position: absolute; top: 10px; width:100%; text-align: center;z-index:1' ;> <a href='https://github.com/AR-js-org/AR.js/' target='_blank'>AR.js</a> - default setting - webcam + hiro + profile + lerp <br /> Contact me any time at <a href='https://twitter.com/nicolocarp' target='_blank'>@nicolocarp</a> </div> <script> ////////////////////////////////////////////////////////////////////////////////// // Init ////////////////////////////////////////////////////////////////////////////////// // init renderer var renderer = new THREE.WebGLRenderer({ // antialias : true, alpha: true }); renderer.setClearColor(new THREE.Color('lightgrey'), 0) // renderer.setPixelRatio( 2 ); 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 = []; var arToolkitContext, arMarkerControls, markerGroup; // init scene and camera var scene = new THREE.Scene(); ////////////////////////////////////////////////////////////////////////////////// // Initialize a basic camera ////////////////////////////////////////////////////////////////////////////////// // Create a camera var camera = new THREE.Camera(); scene.add(camera); markerGroup = new THREE.Group scene.add(markerGroup) //////////////////////////////////////////////////////////////////////////////// // handle arToolkitSource //////////////////////////////////////////////////////////////////////////////// var artoolkitProfile = new THREEx.ArToolkitProfile() artoolkitProfile.sourceWebcam() // artoolkitProfile.sourceVideo(THREEx.ArToolkitContext.baseURL + '../data/videos/headtracking.mp4').kanjiMarker(); // artoolkitProfile.sourceImage(THREEx.ArToolkitContext.baseURL + '../data/images/img.jpg').hiroMarker() var arToolkitSource = new THREEx.ArToolkitSource(artoolkitProfile.sourceParameters) arToolkitSource.init(() => { arToolkitSource.domElement.addEventListener('canplay', () => { console.log( 'canplay', 'actual source dimensions', arToolkitSource.domElement.videoWidth, arToolkitSource.domElement.videoHeight ); initARContext(); }); window.arToolkitSource = arToolkitSource; onResize(); }); // handle resize window.addEventListener('resize', function () { onResize() }) function onResize() { arToolkitSource.onResizeElement() arToolkitSource.copyElementSizeTo(renderer.domElement) if (window.arToolkitContext.arController !== null) { arToolkitSource.copyElementSizeTo(window.arToolkitContext.arController.canvas) } } //////////////////////////////////////////////////////////////////////////////// // initialize arToolkitContext //////////////////////////////////////////////////////////////////////////////// function initARContext() { console.log('initARContext()'); // CONTEXT arToolkitContext = new THREEx.ArToolkitContext(artoolkitProfile.contextParameters) arToolkitContext.init(() => { camera.projectionMatrix.copy(arToolkitContext.getProjectionMatrix()); arToolkitContext.arController.orientation = getSourceOrientation(); arToolkitContext.arController.options.orientation = getSourceOrientation(); console.log('arToolkitContext', arToolkitContext); window.arToolkitContext = arToolkitContext; }); // MARKER arMarkerControls = new THREEx.ArMarkerControls(arToolkitContext, markerGroup, { type: 'pattern', patternUrl: THREEx.ArToolkitContext.baseURL + '../data/data/patt.hiro', }) console.log('ArMarkerControls', arMarkerControls); window.arMarkerControls = arMarkerControls; } function getSourceOrientation() { if (!arToolkitSource) { return null; } console.log( 'actual source dimensions', arToolkitSource.domElement.videoWidth, arToolkitSource.domElement.videoHeight ); if (arToolkitSource.domElement.videoWidth > arToolkitSource.domElement.videoHeight) { console.log('source orientation', 'landscape'); return 'landscape'; } else { console.log('source orientation', 'portrait'); return 'portrait'; } } // update artoolkit on every frame onRenderFcts.push(function () { if (!arToolkitContext || !arToolkitSource || !arToolkitSource.ready) { return; } arToolkitContext.update(arToolkitSource.domElement) }) ////////////////////////////////////////////////////////////////////////////////// // add an object in the scene ////////////////////////////////////////////////////////////////////////////////// var markerScene = new THREE.Scene() markerGroup.add(markerScene) var mesh = new THREE.AxesHelper() markerScene.add(mesh) // add a torus knot var geometry = new THREE.BoxGeometry(1, 1, 1); var material = new THREE.MeshNormalMaterial({ transparent: true, opacity: 0.5, side: THREE.DoubleSide }); var mesh = new THREE.Mesh(geometry, material); mesh.position.y = geometry.parameters.height / 2 markerScene.add(mesh) var geometry = new THREE.TorusKnotGeometry(0.3, 0.1, 64, 16); var material = new THREE.MeshNormalMaterial(); var mesh = new THREE.Mesh(geometry, material); mesh.position.y = 0.5 markerScene.add(mesh); onRenderFcts.push(function (delta) { mesh.rotation.x += delta * Math.PI }) ////////////////////////////////////////////////////////////////////////////////// // 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>