From efcb6d73c8b211ffa44e3fbf09c4c170661b6359 Mon Sep 17 00:00:00 2001 From: Jerome Etienne Date: Wed, 5 Jul 2017 12:41:10 +0100 Subject: [PATCH] more work on aframe --- aframe/aframe-ar0.js | 235 ++++++++++++++++++ aframe/examples/hatsune.html | 2 +- aframe/examples/minecraft-launch-demo.html | 2 +- aframe/examples/minecraft.html | 2 +- aframe/examples/minimal.html | 2 +- .../post-XX-how-to-use-arjs-with-aframe.md | 33 +-- docs/posts/post-iram.md | 25 +- 7 files changed, 268 insertions(+), 33 deletions(-) create mode 100644 aframe/aframe-ar0.js diff --git a/aframe/aframe-ar0.js b/aframe/aframe-ar0.js new file mode 100644 index 0000000..9817322 --- /dev/null +++ b/aframe/aframe-ar0.js @@ -0,0 +1,235 @@ +////////////////////////////////////////////////////////////////////////////// +// Code Separator +////////////////////////////////////////////////////////////////////////////// + +AFRAME.registerSystem('artoolkit', { + schema: { + debug : { + type: 'boolean', + default: false + }, + detectionMode : { + type: 'string', + default: 'mono', + }, + matrixCodeType : { + type: 'string', + default: '3x3', + }, + cameraParametersUrl : { + type: 'string', + }, + maxDetectionRate : { + type: 'number', + default: 60 + }, + sourceType : { + type: 'string', + default: 'webcam', + }, + sourceUrl : { + type: 'string', + }, + sourceWidth : { + type: 'number', + default: 640 + }, + sourceHeight : { + type: 'number', + default: 480 + }, + displayWidth : { + type: 'number', + default: 640 + }, + displayHeight : { + type: 'number', + default: 480 + }, + canvasWidth : { + type: 'number', + default: 640 + }, + canvasHeight : { + type: 'number', + default: 480 + }, + }, + + ////////////////////////////////////////////////////////////////////////////// + // Code Separator + ////////////////////////////////////////////////////////////////////////////// + + + init: function () { + var _this = this + + if( this.data.cameraParametersUrl === '' ){ + this.data.cameraParametersUrl = THREEx.ArToolkitContext.baseURL+'../data/data/camera_para.dat' + } + + //////////////////////////////////////////////////////////////////////////////// + // handle arToolkitSource + //////////////////////////////////////////////////////////////////////////////// + + var arToolkitSource = new THREEx.ArToolkitSource(this.data) + this.arToolkitSource = arToolkitSource + arToolkitSource.init(function onReady(){ + // handle resize of renderer + onResize() + + // kludge to write a 'resize' event + var startedAt = Date.now() + function tick(){ + if( Date.now() - startedAt > 10*1000 ) return + window.dispatchEvent(new Event('resize')); + setTimeout(tick, 1000/60) + } + setTimeout(tick, 1000/60) + }) + + // handle resize + window.addEventListener('resize', onResize) + function onResize(){ + // handle arToolkitSource resize + // var rendererDomElement = _this.sceneEl.renderer ? _this.sceneEl.renderer.domElement : undefined + // arToolkitSource.onResize(rendererDomElement) + + // var rendererDomElement = _this.sceneEl.renderer ? _this.sceneEl.renderer.domElement : undefined + // console.log('dd', _this.sceneEl.renderer.domElement) + + // ugly kludge to get resize on aframe... not even sure it works + arToolkitSource.onResize(document.body) + arToolkitSource.domElement.style.marginLeft = '0px' + + + var buttonElement = document.querySelector('.a-enter-vr') + if( buttonElement ){ + buttonElement.style.position = 'fixed' + } + } + //////////////////////////////////////////////////////////////////////////////// + // initialize arToolkitContext + //////////////////////////////////////////////////////////////////////////////// + + // create atToolkitContext + var arToolkitContext = new THREEx.ArToolkitContext(this.data) + this.arToolkitContext = arToolkitContext + // initialize it + arToolkitContext.init(function onCompleted(){ + // // copy projection matrix to camera + // var projectionMatrixArr = arToolkitContext.arController.getCameraMatrix(); + // _this.sceneEl.camera.projectionMatrix.fromArray(projprojectionMatrixArrectionMatrix); + }) + }, + + tick : function(now, delta){ + if( this.arToolkitSource.ready === false ) return + + // var projectionMatrixArr = this.arToolkitContext.arController.getCameraMatrix(); + // this.sceneEl.camera.projectionMatrix.fromArray(projectionMatrixArr); + + // copy projection matrix to camera + if( this.arToolkitContext.arController !== null ){ + this.sceneEl.camera.projectionMatrix.copy( this.arToolkitContext.getProjectionMatrix() ); + } + + this.arToolkitContext.update( this.arToolkitSource.domElement ) + }, +}); + + +////////////////////////////////////////////////////////////////////////////// +// Code Separator +////////////////////////////////////////////////////////////////////////////// +AFRAME.registerComponent('artoolkitmarker', { + dependencies: ['artoolkit'], + schema: { + size: { + type: 'number', + default: 1 + }, + type: { + type: 'string', + default : 'unknown', + }, + patternUrl: { + type: 'string', + }, + barcodeValue: { + type: 'number' + }, + changeMatrixMode: { + type: 'string', + default : 'modelViewMatrix', + }, + minConfidence: { + type: 'number' + }, + preset: { + type: 'string', + } + }, + init: function () { + // honor this.data.preset + if( this.data.preset === 'hiro' ){ + this.data.type = 'pattern' + this.data.patternUrl = THREEx.ArToolkitContext.baseURL+'../data/data/patt.hiro' + }else if( this.data.preset === 'kanji' ){ + this.data.type = 'pattern' + this.data.patternUrl = THREEx.ArToolkitContext.baseURL+'../data/data/patt.kanji' + }else { + console.assert( this.data.preset === '', 'illegal preset value '+this.data.preset) + } + // actually init arMarkerControls + var artoolkitContext = this.el.sceneEl.systems.artoolkit.arToolkitContext + this.arMarkerControls = new THREEx.ArMarkerControls(artoolkitContext, this.el.object3D, this.data) + }, + remove : function(){ + this.arMarkerControls.dispose() + }, + update: function () { + // FIXME this mean to change the recode in trackBarcodeMarkerId ? + // var markerRoot = this.el.object3D; + // markerRoot.userData.size = this.data.size; + }, + tick: function(){ + if( this.data.changeMatrixMode === 'cameraTransformMatrix' ){ + this.el.sceneEl.object3D.visible = this.el.object3D.visible; + } + } +}); + +////////////////////////////////////////////////////////////////////////////// +// define some primitives shortcuts +////////////////////////////////////////////////////////////////////////////// + +AFRAME.registerPrimitive('a-marker', AFRAME.utils.extendDeep({}, AFRAME.primitives.getMeshMixin(), { + defaultComponents: { + artoolkitmarker: {}, + }, + mappings: { + 'type': 'artoolkitmarker.type', + 'size': 'artoolkitmarker.size', + 'url': 'artoolkitmarker.patternUrl', + 'value': 'artoolkitmarker.barcodeValue', + 'preset': 'artoolkitmarker.preset', + 'minConfidence': 'artoolkitmarker.minConfidence', + } +})); + +AFRAME.registerPrimitive('a-marker-camera', AFRAME.utils.extendDeep({}, AFRAME.primitives.getMeshMixin(), { + defaultComponents: { + artoolkitmarker: { + changeMatrixMode: 'cameraTransformMatrix' + }, + camera: true, + }, + mappings: { + 'type': 'artoolkitmarker.type', + 'size': 'artoolkitmarker.size', + 'url': 'artoolkitmarker.patternUrl', + 'value': 'artoolkitmarker.barcodeValue', + 'preset': 'artoolkitmarker.preset', + } +})); diff --git a/aframe/examples/hatsune.html b/aframe/examples/hatsune.html index 7298a7b..0e65d34 100644 --- a/aframe/examples/hatsune.html +++ b/aframe/examples/hatsune.html @@ -1,6 +1,6 @@ - + diff --git a/aframe/examples/minecraft-launch-demo.html b/aframe/examples/minecraft-launch-demo.html index b69268c..c69ef02 100644 --- a/aframe/examples/minecraft-launch-demo.html +++ b/aframe/examples/minecraft-launch-demo.html @@ -1,6 +1,6 @@ - + diff --git a/aframe/examples/minecraft.html b/aframe/examples/minecraft.html index d7f5891..b32fe71 100644 --- a/aframe/examples/minecraft.html +++ b/aframe/examples/minecraft.html @@ -1,6 +1,6 @@ - + diff --git a/aframe/examples/minimal.html b/aframe/examples/minimal.html index fc4aaaf..09fe090 100644 --- a/aframe/examples/minimal.html +++ b/aframe/examples/minimal.html @@ -1,5 +1,5 @@ - + diff --git a/docs/posts/post-XX-how-to-use-arjs-with-aframe.md b/docs/posts/post-XX-how-to-use-arjs-with-aframe.md index 4030a98..c96d236 100644 --- a/docs/posts/post-XX-how-to-use-arjs-with-aframe.md +++ b/docs/posts/post-XX-how-to-use-arjs-with-aframe.md @@ -9,29 +9,29 @@ Dont worry, you can do it with only 8 line of html. AR.js is an efficient Augmented Reality solution on the Web. It runs 100% in your web browser, this means no app to install! There is no need for a specific device either e.g. tango or iphone. -You can use it with your own phone. Depending on which device you have, it -can run very fast, up to 60fps on 2year-old phones! +It run on all mobile platforms: Android, iOS11 and Windows mobile. +You can use it with your own phone. +Depending on your device, it can run very fast, up to 60fps on 2year-old phones! -You will not be limited by your OS because AR.js runs on every platforms: Android, iOS11 and Windows mobile. -And most importantly, it is open source and free of charge. The code is all available on github. -I wanted to make sure that AR.js was working well with a-frame. A-frame is very easy to use. -Thus, combining a-frame and AR.js it's easier for everybody to create AR content on the web. +On top of that, it is open source and free of charge. The code is all available on [github](https://github.com/jeromeetienne/ar.js). +A-frame is very easy to use so i wanted to make sure that AR.js was working well with a-frame. +Thus, combining a-frame and AR.js, it's simple for everybody to create AR content on the web. Sounds good? Let's see how to use it. # Show Dont Tell Today you can make [augmented reality in 10 Lines of HTML](https://medium.com/arjs/augmented-reality-in-10-lines-of-html-4e193ea9fdbf), isn't the web amazing ? -You can try live on [codepen](https://codepen.io/jeromeetienne/pen/mRqqzb). +It is really that simple, you can try live on [codepen](https://codepen.io/jeromeetienne/pen/mRqqzb). ```html - + - + @@ -40,13 +40,14 @@ You can try live on [codepen](https://codepen.io/jeromeetienne/pen/mRqqzb). ``` -In this scene, the camera will be moved by AR.js, and the origin of your scene -is at the center of the marker. All the rest is normal a-frame. +In this scene, the camera is be moved by AR.js, and +the origin of your scene is at the center of the marker. +All the rest is normal a-frame. So if you want to add new objects in the augmented reality, just add it -close to the ``````. +near the ``````. -# How to add ar.js in your a-frame +# How to add AR.js in your A-Frame Project This is 2 steps only 1. Tell ar.js to start a-aframe @@ -159,7 +160,7 @@ matrixCodeType: 3x3 ```html +arjs='sourceType: webcam; detectionMode: mono_and_matrix; matrixCodeType: 3x3;'> ``` @@ -207,10 +208,10 @@ TODO transition ? - e.g. you can see it in this [multiple independent markers example](https://jeromeetienne.github.io/AR.js/aframe/examples/multiple-independent-markers.html) ```html - + - + diff --git a/docs/posts/post-iram.md b/docs/posts/post-iram.md index ce8a4f0..bc9af80 100644 --- a/docs/posts/post-iram.md +++ b/docs/posts/post-iram.md @@ -4,20 +4,19 @@ There are good reasons to believe that web apps will begin to look more and more **Progressive Web Apps (PWA)** — PWA are a website building methodology that enables website to be treated by the browser like an app, rather than an old school website. It enables web sites to have live updates, push notifications, launch the web site from the home screen, SEO discoverability, offline usage and more. This circumvents many of the reasons why users prefer apps, which will make it easier for publishers to engage users without the high friction need for app download. Some notable companies who shifted to PWA are AliExpress, The Financial Times and Lyft. Check out the video below to learn more about PWA. -**WebGL 2.0** — A javascript graphics library that enables rendering of high quality 3D graphics content on the browser. It is built on top of OpenGL ES (Embedded System) which allows it to use the mobile device’s GPU, which is a massive improvement compared to running it on the CPU. WebGL is supported by all major browsers which helps standardize web content creation. +**WebAssembly** — This is a new low level, Assembly-like, programming language that enables code written in non-javascript to run in the browser. +It is efficient, lightning fast, and backward compatible with asm.js. +Why is WebAssembly so important? Wasm enables to leverage code written for native environment and run it in the browser. +So the web can reuse native code and run it faster than normal javascript. +People like unity or unreal are obviously interested and are actively collaborating with browser makers to make it happen. -TODO to reduce +**WebGL 2.0** — A javascript graphics API that enables rendering of high quality 3D graphics content on the browser. It is built on top of OpenGL ES (Embedded System) which allows it to use the mobile device’s GPU, which is a massive improvement compared to running it on the CPU. WebGL is supported by all major browsers which helps standardize web content creation. - -**WebAssembly** — This is a new low level, Assembly-like, programming language that enables code written in non-javascript to run in the browser. It is efficient, lightning fast, and backward compatible with asm.js. Why is this so important? Wasm will enable graphics-heavy applications to run within the browser in native-like speed and fidelity. - -TODO put some truth into this -https://hacks.mozilla.org/category/code-cartoons/a-cartoon-intro-to-webassembly/ - -**WebRTC** — Web Real Time Communication is a 5 year old standard that allows browsers to perform real time communications (in our case, access to the device’s camera and microphone), without relaying on 3rd party plugins such as Java, Flash, Silverlight which need to be updated regularly (due to security reasons). Not all mobile devices support WebRTC, but once they do, this would allow for a standardized way for developers to use Javascript libraries such as three.js and ar.js to enable real time AR experiences within a web app environment. - -TODO to reduce +**WebRTC** — Web Real Time Communication is a well established standard that allows browsers to perform real time communications (in our case, access to the device’s camera and microphone). It works on all mobiles (IOS11 just added getUserMedia) and allow for a standardized way for developers to use Javascript libraries such as three.js and ar.js to enable real time AR experiences within a web app environment. **Shared Memory and Multi-Threading**: - -https://blogs.windows.com/msedgedev/2017/04/20/improved-javascript-performance-webassembly-shared-memory/ +WebWorkers is a way to run code on multiple CPU cores at the same time. +Typically a modern phone got 4 CPU, to leverage all of them would greatly increase the CPU available to the application. +WebWorkers exists for a long time, but recently shared memory and atomic got added. +It definitly helps computer vision application. They can now use all CPU core, avoid unnecessary copy and handle +shared rescources efficiently with atomic locks. -- GitLab