diff --git a/Marker_Printout_AR_demo.pdf b/Marker_Printout_AR_demo.pdf new file mode 100644 index 0000000000..b5ba31a38f Binary files /dev/null and b/Marker_Printout_AR_demo.pdf differ diff --git a/README.md b/README.md index 89281daba8..61d5bc0d51 100644 --- a/README.md +++ b/README.md @@ -1 +1,30 @@ # AR-Examples +The examples from [Lee Stemkoski](https://github.com/stemkoski/AR-Examples) was forked and a few examples are added. +* for using these examples, print out the [markers](markers/Marker_Printout_AR_demo.pdf) and +* switch on the WebCam and let browser to access the WebCam. +* place the marker mentioned in the [demo page](https://niebert.github.io/AR-Examples) in front of the camera and move the markers +* in some AR examples multiple markers can be used and different objects can be places +* also [360-degree (equirectangular) images](https://www.github.com/niebert/HuginSample) are used to and you could use e.g. the [hiro-marker](markers/Marker_Printout_AR_demo.pdf) to look around + +Check out the online demos with: +## [Online-Demo](https://niebert.github.io/AR-Examples) +* [Download ZIP-file](https://github.com/niebert/AR-Examples/archive/refs/heads/master.zip) of this repository +* see also [Wikiversity learning resource about 3D-modelling](https://en.wikiversity.org/wiki/3D_Modelling/Examples/AR_with_Markers) +* [HuginSample - Equirectangular Images](https://www.github.com/niebert/HuginSample) or [AFrame Navigation](https://niebert.github.io/aframe360navigation/) + +## 3D-Models on Marker +Sketchfab publishes 3D-Models as creative commons. One the CC-BY-4.0 models a dinosaur (Spinosaurus) is used as a 3D model on a marker. The model is called +* "[primal carnage spinosaurus](https://skfb.ly/pswyN))" (URL: https://skfb.ly/pswyN) created by `seth the yutyrannus`. +* The 3D model is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/). +* ***AR-Web-Demo:*** [Spinosaurus on AR-Marker](https://niebert.github.io/AR-Examples/spinosaurus_hiro_ar.html) - ***VR-Web-Demo:*** [Spinosaurus in VR](https://niebert.github.io/HuginSample/spinosaurus_rieselfelder_aframe.html) +* GLB-File: [model3d/primal_carnage_spinosaurus_small.glb](model3d/primal_carnage_spinosaurus_small.glb) +![Spinosaurus on AR-Marker](./img/spinosaurus_on_ar_marker.png) + +* **(Print Marker)** Use Hiro-Marker as print out +* **(Display 3D Model in Browser)** Start [Web-Demo - Spinosaurus on AR-Marker - "Hiro"](https://niebert.github.io/AR-Examples/spinosaurus_hiro_ar.html) +* **(Marker in Camera Viewport)** Allow camera to record Hiro-Marker in Webcam. +* **(3D Model in Webpage displayed on Marker)** Dinosaur will be placed on Hiro-Marker in camera image. +* **(Coordinate System)** Hiro marker (and any other marker) defines in the asymmetric shape a coordinate system in which the objects are placed. +* **(Scaling of Object - Marker Size)** The size of the Hiro marker defines the unit length in the coordinate system. E.g. triple size of printed Hiro marker scales the objects by the factor 3. + +![Hiro-Marker](./markers/hiro.png) diff --git a/a_hiro.html b/a_hiro.html new file mode 100644 index 0000000000..2921763b2a --- /dev/null +++ b/a_hiro.html @@ -0,0 +1,46 @@ + + + + + Receiver of Params + + + +

Verwenden Sie den folgenden Marker

+
+
+ +
+
+ + + + + diff --git a/a_marker.html b/a_marker.html new file mode 100644 index 0000000000..43086b3e8d --- /dev/null +++ b/a_marker.html @@ -0,0 +1,47 @@ + + + + + Receiver of Params + + + +

Use the following Marker for the AR-Example

+
+
+ +
+
+ + + + + diff --git a/basic-scene-hiro.html b/basic-scene-hiro.html new file mode 100644 index 0000000000..c7b02da31e --- /dev/null +++ b/basic-scene-hiro.html @@ -0,0 +1,157 @@ + + + + Hello, AR Cubes! + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/basic_cube_colored_threes.html b/basic_cube_colored_threes.html new file mode 100644 index 0000000000..1abe14a261 --- /dev/null +++ b/basic_cube_colored_threes.html @@ -0,0 +1,142 @@ + + + + Hello, world! + + + + + + + + + + + + + + + + + + diff --git a/css/index.css b/css/index.css index 0ff7649e43..67d5a42aab 100644 --- a/css/index.css +++ b/css/index.css @@ -37,6 +37,21 @@ body -webkit-border-radius: 15px 15px 15px 15px; border-radius: 15px 15px 15px 15px; } +.link4text { + font-size: 16px; + font-weight: normal; + font-variantx: small-caps; + color:#00c; + text-shadow: 1px 1px 0px #aaa; + margin: 13px 0px 0px 0px; + text-decoration: none; + + -webkit-transition: all 300ms ease-in-out; + -moz-transition: all 300ms ease-in-out; + -o-transition: all 300ms ease-in-out; + -ms-transition: all 300ms ease-in-out; + transition: all 300ms ease-in-out; +} /* Page text links */ a @@ -130,4 +145,4 @@ a:hover .superImage color:#004; text-align: center; text-shadow: -1px -1px 2px #fff, 1px 1px 3px #000; -} \ No newline at end of file +} diff --git a/globe-multi-marker.html b/globe-multi-marker.html index d24e1dacb0..dac62df062 100644 --- a/globe-multi-marker.html +++ b/globe-multi-marker.html @@ -13,11 +13,16 @@ + - @@ -62,7 +67,7 @@ deltaTime = 0; totalTime = 0; keyboard = new Keyboard(); - + //////////////////////////////////////////////////////////// // setup arToolkitSource //////////////////////////////////////////////////////////// @@ -73,26 +78,26 @@ function onResize() { - arToolkitSource.onResize() - arToolkitSource.copySizeTo(renderer.domElement) + arToolkitSource.onResize() + arToolkitSource.copySizeTo(renderer.domElement) if ( arToolkitContext.arController !== null ) { - arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) - } + arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) + } } arToolkitSource.init(function onReady(){ onResize() }); - + // handle resize event window.addEventListener('resize', function(){ onResize() }); - + //////////////////////////////////////////////////////////// // setup arToolkitContext - //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// // create atToolkitContext arToolkitContext = new THREEx.ArToolkitContext({ @@ -100,7 +105,7 @@ detectionMode: 'mono', maxDetectionRate: 30, }); - + // copy projection matrix to camera when initialization complete arToolkitContext.init( function onCompleted(){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); @@ -111,41 +116,41 @@ //////////////////////////////////////////////////////////// markerNames = ["kanji", "letterA", "letterB"]; - + markerArray = []; - + for (let i = 0; i < markerNames.length; i++) { let marker = new THREE.Group(); scene.add(marker); markerArray.push(marker); - + let markerControls = new THREEx.ArMarkerControls(arToolkitContext, marker, { type: 'pattern', patternUrl: "data/" + markerNames[i] + ".patt", }); - + let markerGroup = new THREE.Group(); marker.add(markerGroup); } - + //////////////////////////////////////////////////////////// // setup scene //////////////////////////////////////////////////////////// - + sceneGroup = new THREE.Group(); - + let loader = new THREE.TextureLoader(); - - let geometry1 = new THREE.SphereGeometry(1, 32,32); + + let geometry1 = new THREE.SphereGeometry(1, 32,32); let texture = loader.load( 'images/earth-sphere.jpg' ); let material1 = new THREE.MeshLambertMaterial( { map: texture, opacity: 0.75 } ); globe = new THREE.Mesh( geometry1, material1 ); globe.position.y = 1; - sceneGroup.add(globe); - + sceneGroup.add(globe); + markerArray[0].children[0].add( sceneGroup ); currentMarkerName = markerNames[0]; - + let pointLight = new THREE.PointLight( 0xffffff, 1, 50 ); camera.add( pointLight ); } @@ -154,9 +159,9 @@ function update() { keyboard.update(); - + globe.rotation.y += 0.01; - + let anyMarkerVisible = false; for (let i = 0; i < markerArray.length; i++) { @@ -169,12 +174,12 @@ currentMarkerName = markerNames[i]; // console.log("Switching to " + currentMarkerName); } - + let p = markerArray[i].children[0].getWorldPosition(); let q = markerArray[i].children[0].getWorldQuaternion(); let s = markerArray[i].children[0].getWorldScale(); let lerpAmount = 0.5; - + scene.add(sceneGroup); sceneGroup.position.lerp(p, lerpAmount); sceneGroup.quaternion.slerp(q, lerpAmount); @@ -188,9 +193,9 @@ { // console.log("No marker currently visible."); } - + let baseMarker = markerArray[0]; - + // update relative positions of markers for (let i = 1; i < markerArray.length; i++) { @@ -199,15 +204,15 @@ if ( baseMarker.visible && currentMarker.visible ) { // console.log("updating marker " + i " -> base offset"); - + let relativePosition = currentMarker.worldToLocal( baseMarker.position.clone() ); currentGroup.position.copy( relativePosition ); - + let relativeRotation = currentMarker.quaternion.clone().inverse().multiply( baseMarker.quaternion.clone() ); currentGroup.quaternion.copy( relativeRotation ); } } - + // update artoolkit on every frame if ( arToolkitSource.ready !== false ) arToolkitContext.update( arToolkitSource.domElement ); @@ -233,4 +238,4 @@ - \ No newline at end of file + diff --git a/globe.html b/globe.html index 236fec01f9..51af0b6602 100644 --- a/globe.html +++ b/globe.html @@ -12,11 +12,16 @@ + - @@ -58,7 +63,7 @@ clock = new THREE.Clock(); deltaTime = 0; totalTime = 0; - + //////////////////////////////////////////////////////////// // setup arToolkitSource //////////////////////////////////////////////////////////// @@ -69,33 +74,33 @@ function onResize() { - arToolkitSource.onResize() - arToolkitSource.copySizeTo(renderer.domElement) + arToolkitSource.onResize() + arToolkitSource.copySizeTo(renderer.domElement) if ( arToolkitContext.arController !== null ) { - arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) - } + arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) + } } arToolkitSource.init(function onReady(){ onResize() }); - + // handle resize event window.addEventListener('resize', function(){ onResize() }); - + //////////////////////////////////////////////////////////// // setup arToolkitContext - //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// // create atToolkitContext arToolkitContext = new THREEx.ArToolkitContext({ cameraParametersUrl: 'data/camera_para.dat', detectionMode: 'mono' }); - + // copy projection matrix to camera when initialization complete arToolkitContext.init( function onCompleted(){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); @@ -113,24 +118,24 @@ }) let geometry1 = new THREE.SphereGeometry(1, 32,32); - + let loader = new THREE.TextureLoader(); let texture = loader.load( 'images/earth-sphere.jpg', render ); let material1 = new THREE.MeshLambertMaterial( { map: texture, opacity: 0.5 } ); - + mesh1 = new THREE.Mesh( geometry1, material1 ); mesh1.position.y = 1; - + markerRoot1.add( mesh1 ); - + let pointLight = new THREE.PointLight( 0xffffff, 1, 100 ); pointLight.position.set(0.5,3,2); // create a mesh to help visualize the position of the light - pointLight.add( - new THREE.Mesh( - new THREE.SphereBufferGeometry( 0.05, 16,8 ), - new THREE.MeshBasicMaterial({ color: 0xffffff, opacity: 0.5 }) - ) + pointLight.add( + new THREE.Mesh( + new THREE.SphereBufferGeometry( 0.05, 16,8 ), + new THREE.MeshBasicMaterial({ color: 0xffffff, opacity: 0.5 }) + ) ); markerRoot1.add( pointLight ); } @@ -164,4 +169,4 @@ - \ No newline at end of file + diff --git a/hello-cube.html b/hello-cube.html index 51a32c2f2d..baffa4e2c0 100644 --- a/hello-cube.html +++ b/hello-cube.html @@ -12,11 +12,16 @@ + - @@ -40,7 +45,7 @@ let ambientLight = new THREE.AmbientLight( 0xcccccc, 0.5 ); scene.add( ambientLight ); - + camera = new THREE.Camera(); scene.add(camera); @@ -58,7 +63,7 @@ clock = new THREE.Clock(); deltaTime = 0; totalTime = 0; - + //////////////////////////////////////////////////////////// // setup arToolkitSource //////////////////////////////////////////////////////////// @@ -69,33 +74,33 @@ function onResize() { - arToolkitSource.onResize() - arToolkitSource.copySizeTo(renderer.domElement) + arToolkitSource.onResize() + arToolkitSource.copySizeTo(renderer.domElement) if ( arToolkitContext.arController !== null ) { - arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) - } + arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) + } } arToolkitSource.init(function onReady(){ onResize() }); - + // handle resize event window.addEventListener('resize', function(){ onResize() }); - + //////////////////////////////////////////////////////////// // setup arToolkitContext - //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// // create atToolkitContext arToolkitContext = new THREEx.ArToolkitContext({ cameraParametersUrl: 'data/camera_para.dat', detectionMode: 'mono' }); - + // copy projection matrix to camera when initialization complete arToolkitContext.init( function onCompleted(){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); @@ -117,11 +122,11 @@ transparent: true, opacity: 0.5, side: THREE.DoubleSide - }); - + }); + mesh1 = new THREE.Mesh( geometry1, material1 ); mesh1.position.y = 0.5; - + markerRoot1.add( mesh1 ); } @@ -152,4 +157,4 @@ - \ No newline at end of file + diff --git a/hole-box.html b/hole-box.html index 3b819d9f6f..7c49b40389 100644 --- a/hole-box.html +++ b/hole-box.html @@ -12,11 +12,17 @@ + + - @@ -40,7 +46,7 @@ let ambientLight = new THREE.AmbientLight( 0xcccccc, 1.0 ); scene.add( ambientLight ); - + camera = new THREE.Camera(); scene.add(camera); @@ -58,7 +64,7 @@ clock = new THREE.Clock(); deltaTime = 0; totalTime = 0; - + //////////////////////////////////////////////////////////// // setup arToolkitSource //////////////////////////////////////////////////////////// @@ -69,33 +75,33 @@ function onResize() { - arToolkitSource.onResize() - arToolkitSource.copySizeTo(renderer.domElement) + arToolkitSource.onResize() + arToolkitSource.copySizeTo(renderer.domElement) if ( arToolkitContext.arController !== null ) { - arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) - } + arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) + } } arToolkitSource.init(function onReady(){ onResize() }); - + // handle resize event window.addEventListener('resize', function(){ onResize() }); - + //////////////////////////////////////////////////////////// // setup arToolkitContext - //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// // create atToolkitContext arToolkitContext = new THREEx.ArToolkitContext({ cameraParametersUrl: 'data/camera_para.dat', detectionMode: 'mono' }); - + // copy projection matrix to camera when initialization complete arToolkitContext.init( function onCompleted(){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); @@ -122,25 +128,25 @@ transparent : true, map: texture, side: THREE.BackSide - }); - + }); + mesh1 = new THREE.Mesh( geometry1, material1 ); mesh1.position.y = -1; - + markerRoot1.add( mesh1 ); - + // the invisibility cloak (box with a hole) let geometry0 = new THREE.BoxGeometry(2,2,2); geometry0.faces.splice(4, 2); // make hole by removing top two triangles - + let material0 = new THREE.MeshBasicMaterial({ colorWrite: false }); - + let mesh0 = new THREE.Mesh( geometry0, material0 ); mesh0.scale.set(1,1,1).multiplyScalar(1.01); mesh0.position.y = -1; - markerRoot1.add(mesh0); + markerRoot1.add(mesh0); } @@ -170,4 +176,4 @@ - \ No newline at end of file + diff --git a/hole-plane.html b/hole-plane.html index 8711401256..a971949e00 100644 --- a/hole-plane.html +++ b/hole-plane.html @@ -12,11 +12,16 @@ + - @@ -40,7 +45,7 @@ let ambientLight = new THREE.AmbientLight( 0xcccccc, 1.0 ); scene.add( ambientLight ); - + camera = new THREE.Camera(); scene.add(camera); @@ -58,7 +63,7 @@ clock = new THREE.Clock(); deltaTime = 0; totalTime = 0; - + //////////////////////////////////////////////////////////// // setup arToolkitSource //////////////////////////////////////////////////////////// @@ -69,33 +74,33 @@ function onResize() { - arToolkitSource.onResize() - arToolkitSource.copySizeTo(renderer.domElement) + arToolkitSource.onResize() + arToolkitSource.copySizeTo(renderer.domElement) if ( arToolkitContext.arController !== null ) { - arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) - } + arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) + } } arToolkitSource.init(function onReady(){ onResize() }); - + // handle resize event window.addEventListener('resize', function(){ onResize() }); - + //////////////////////////////////////////////////////////// // setup arToolkitContext - //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// // create atToolkitContext arToolkitContext = new THREEx.ArToolkitContext({ cameraParametersUrl: 'data/camera_para.dat', detectionMode: 'mono' }); - + // copy projection matrix to camera when initialization complete arToolkitContext.init( function onCompleted(){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); @@ -122,27 +127,27 @@ transparent : true, map: texture, side: THREE.BackSide - }); - + }); + mesh1 = new THREE.Mesh( geometry1, material1 ); mesh1.position.y = -1; - + markerRoot1.add( mesh1 ); - + // the invisibility cloak (plane with a hole) let geometry0 = new THREE.PlaneGeometry(18,18, 9,9); geometry0.faces.splice(80, 2); // make hole by removing top two triangles geometry0.faceVertexUvs[0].splice(80, 2); - + let material0 = new THREE.MeshBasicMaterial({ // map: loader.load( 'images/color-grid.png' ), // for testing placement colorWrite: false }); - + let mesh0 = new THREE.Mesh( geometry0, material0 ); - + mesh0.rotation.x = -Math.PI/2; - markerRoot1.add(mesh0); + markerRoot1.add(mesh0); } @@ -172,4 +177,4 @@ - \ No newline at end of file + diff --git a/hole-ring.html b/hole-ring.html index 16e706118e..8752b9f2dd 100644 --- a/hole-ring.html +++ b/hole-ring.html @@ -12,11 +12,16 @@ + - @@ -40,7 +45,7 @@ let ambientLight = new THREE.AmbientLight( 0xcccccc, 1.0 ); scene.add( ambientLight ); - + camera = new THREE.Camera(); scene.add(camera); @@ -58,7 +63,7 @@ clock = new THREE.Clock(); deltaTime = 0; totalTime = 0; - + //////////////////////////////////////////////////////////// // setup arToolkitSource //////////////////////////////////////////////////////////// @@ -69,33 +74,33 @@ function onResize() { - arToolkitSource.onResize() - arToolkitSource.copySizeTo(renderer.domElement) + arToolkitSource.onResize() + arToolkitSource.copySizeTo(renderer.domElement) if ( arToolkitContext.arController !== null ) { - arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) - } + arToolkitSource.copySizeTo(arToolkitContext.arController.canvas) + } } arToolkitSource.init(function onReady(){ onResize() }); - + // handle resize event window.addEventListener('resize', function(){ onResize() }); - + //////////////////////////////////////////////////////////// // setup arToolkitContext - //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// // create atToolkitContext arToolkitContext = new THREEx.ArToolkitContext({ cameraParametersUrl: 'data/camera_para.dat', detectionMode: 'mono' }); - + // copy projection matrix to camera when initialization complete arToolkitContext.init( function onCompleted(){ camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() ); @@ -125,11 +130,11 @@ transparent : true, map: texture, side: THREE.BackSide - }); + }); mesh1 = new THREE.Mesh( geometry1, material1 ); mesh1.position.y = -2; markerRoot1.add( mesh1 ); - + // the invisibility cloak (ring; has circular hole) let geometry0 = new THREE.RingGeometry(1,9, 32); let material0 = new THREE.MeshBasicMaterial({ @@ -138,7 +143,7 @@ }); let mesh0 = new THREE.Mesh( geometry0, material0 ); mesh0.rotation.x = -Math.PI/2; - markerRoot1.add(mesh0); + markerRoot1.add(mesh0); } @@ -168,4 +173,4 @@ - \ No newline at end of file + diff --git a/images/demo/parabolic-path-hiro-kanji.png b/images/demo/parabolic-path-hiro-kanji.png new file mode 100644 index 0000000000..673b12b62f Binary files /dev/null and b/images/demo/parabolic-path-hiro-kanji.png differ diff --git a/images/demo/planetsystem_ar_hiro.png b/images/demo/planetsystem_ar_hiro.png new file mode 100644 index 0000000000..a6d195a0c5 Binary files /dev/null and b/images/demo/planetsystem_ar_hiro.png differ diff --git a/images/demo/rhein1_rodenkirchen.png b/images/demo/rhein1_rodenkirchen.png new file mode 100644 index 0000000000..7dce8a6c22 Binary files /dev/null and b/images/demo/rhein1_rodenkirchen.png differ diff --git a/images/demo/spinosaurus-rieselfelder.png b/images/demo/spinosaurus-rieselfelder.png new file mode 100644 index 0000000000..c1a20e5092 Binary files /dev/null and b/images/demo/spinosaurus-rieselfelder.png differ diff --git a/img/README.md b/img/README.md new file mode 100644 index 0000000000..41ccef3824 --- /dev/null +++ b/img/README.md @@ -0,0 +1 @@ +Equirectangular Images used from https://www.github.com/niebert/HuginSample diff --git a/img/rhein1_rodenkirchen.jpg b/img/rhein1_rodenkirchen.jpg new file mode 100644 index 0000000000..0577130bcf Binary files /dev/null and b/img/rhein1_rodenkirchen.jpg differ diff --git a/img/rhein2_rodenkirchen.jpg b/img/rhein2_rodenkirchen.jpg new file mode 100644 index 0000000000..fcdea59955 Binary files /dev/null and b/img/rhein2_rodenkirchen.jpg differ diff --git a/img/rhein3_rodenkirchen.jpg b/img/rhein3_rodenkirchen.jpg new file mode 100644 index 0000000000..af8cdbbdba Binary files /dev/null and b/img/rhein3_rodenkirchen.jpg differ diff --git a/img/rhein4_rodenkirchen.jpg b/img/rhein4_rodenkirchen.jpg new file mode 100644 index 0000000000..e3d49e5a37 Binary files /dev/null and b/img/rhein4_rodenkirchen.jpg differ diff --git a/img/spinosaurus_on_ar_marker.png b/img/spinosaurus_on_ar_marker.png new file mode 100644 index 0000000000..48f7ed431e Binary files /dev/null and b/img/spinosaurus_on_ar_marker.png differ diff --git a/index.html b/index.html index 5c9407b301..d6fa1bbc7a 100644 --- a/index.html +++ b/index.html @@ -1,98 +1,169 @@ -Three.js and AR.js - examples +AR - Beispiele + -
Three.js and AR.js Examples
+
Augemented Reality

-The goal of this collection is to provide a set of basic and instructive examples that introduce the various features in the Javascript-based Augmented Reality (AR) library, -AR.js. Advanced three.js examples are also included. +Beispiel zum Testen von AR.js. Weitere Beispiele zu three.js findet man auf der homepage.

-Viewing the AR examples will require a device with a camera and one or both of the Hiro and Kanji marker patterns (either printed or displayed on a second device). -

-Source code hosted at GitHub. +Quelle der Beispiele sind auf GitHub zu finden +
- +
Basic Cube

A basic scene that superimposes a cube on a Hiro marker. +

+
- +
Many Cubes

A scene that superimposes different colored cubes on a Hiro, Kanji, and letter markers. + + Marker-PDF-Printout + +
+ + + + + +

- +
- +
Image Texture

An image is positioned to cover a Hiro marker. +

- + + +
360 Degree Scene on a Marker
+

Use a 360 degree image as a aframe/AR.js sky that is positioned around the Hiro marker. The hiro marker define the perspective and view in the 360 degree scene. Keep the marker in the view of the camera. +
+ +

+
+ + +
+ + +
Spinosaurus on Marker
+

Spinosaurus on Hiro marker. Keep the marker in the view of the camera. +Sketchfab publishes 3D-Models as creative commons. One the CC-BY-4.0 models a dinosaur (Spinosaurus) is used as a 3D model on a marker. +The model is called "primal carnage spinosaurus" (URL: https://skfb.ly/pswyN) created +by seth the yutyrannus. The 3D model is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/). See Spinosaurus Source on SketchFab. +Keep the marker in the view of the camera. +
+

+
+ + +
+
Rotating Globe

A rotating globe (illuminated by a point light) is positioned above a Hiro marker. +

- + + +
Planet System - Sun, Earth, Moon
+

A rotating sun, moon and earth is positioned two dependent rotations above a Hiro marker. Created by Irina Shashkov - see Wikiversity learning resource +
+

+
+ +
+
Video Texture

A flat plane, with a video for a texture, is positioned to cover a Hiro marker. +

- +
Shader

A flat plane moves up and down above a Hiro marker; position and tint color are controlled by vertex and fragment shaders. +

- +
Loading 3D Models
-

A 3D model (obj and mtl files) are loaded and displayed above a Hiro marker. +

A 3D model (OBJ and MTL files) are loaded and displayed above a Hiro marker. +OBJ defines the 3D model and the MTL creates the texture and the layer. +

- +
Hole in the Floor (Box)

A "hole in the floor" effect. Uses a box geometry to mask the hidden parts of the hole. +

- +
Hole in the Floor (Plane)
-

Another "hole in the floor" effect, using a plane geometry to mask the hidden parts of the hole. +

Another "hole in the floor" effect, using a plane geometry to mask the hidden parts of the hole. A rear side of a plane is translucent. This feature is used in the +

@@ -101,33 +172,39 @@
Hole in the Floor (Ring)

A cylindrical "hole in the floor" effect, using a ring geometry to mask the hidden parts of the hole. +

- +

Water Effect (no AR)
-

An animated effect (using shaders) that looks like water flowing -out from a central point and being absorbed into the floor. (No AR.)

+

An animated effect (using shaders) that looks like water flowing +out from a central point and being absorbed into the floor. (No AR.) +
+


Water Effect (AR version)
-

An animated effect (using shaders) that looks like water flowing -out from a cylindrical hole (displayed above a Hiro marker), and being absorbed into the floor. -
Video preview here.

+

An animated effect (using shaders) that looks like water flowing +out from a cylindrical hole (displayed above a Hiro marker), and being absorbed into the floor. +
Video preview here. +
+

+

Magic Cube Effect
-

Creates a "magic cube effect" that overlays a cube covered with six AR markers in this pattern. -
Video preview here.

+

Creates a "magic cube effect" that overlays a cube covered with six AR markers +in this pattern. +
Video preview here. +
+

+

@@ -196,6 +278,13 @@
Globe with Multiple Markers

Similar to the Rotating Globe example: places a globe over a Kanji marker. If Kanji marker is blocked, uses other markers (letter A and letter B) to position the globe.

+
+ + Marker-PDF-Printout + + + +
@@ -203,22 +292,41 @@
Refraction

Creates a rotating torus knot above a Kanji marker. The surface of the knot refracts the scene behind it. -
Video preview here. -

+
Video preview here. +
+


Shadow
-

Creates a rotating torus knot above a Kanji marker. The knot casts a shadow onto the plane containing the marker.

+

Creates a rotating torus knot above a Kanji marker. The knot casts a shadow onto the plane containing the marker. +
+ +


Shadow Balls
-

Creates four colored bouncing basketballs around a Kanji marker. The balls cast shadows onto the plane containing the marker.

+

Creates four colored bouncing basketballs around a Kanji marker. The balls cast shadows onto the plane containing the Kanji marker. +
+ +

+
+ +
+ + +
Parabolic Path
+

A basketball launches from a Hiro marker and falls towards a Kanji marker, following a parabolic path. The ball casts shadows, and a clipping plane (see above example) is used +to make the ball disappear into the marker. Place hiro-marker and the kanji-marker in front of the webcam. +
+ + +

@@ -226,7 +334,11 @@
Parabolic Path

A basketball launches from a Letter-A marker and falls towards a Letter-B marker, following a parabolic path. The ball casts shadows, and a clipping plane (see above example) is used -to make the ball disappear into the marker.

+to make the ball disappear into the marker. +
+ + +

- +
+
+ GitHub-Repository - Fork +
+
+
+
+
+
+
+
diff --git a/index_stemkoski.html b/index_stemkoski.html new file mode 100644 index 0000000000..5c9407b301 --- /dev/null +++ b/index_stemkoski.html @@ -0,0 +1,251 @@ + + +Three.js and AR.js - examples + + + + +
Three.js and AR.js Examples
+
+The goal of this collection is to provide a set of basic and instructive examples that introduce the various features in the Javascript-based Augmented Reality (AR) library, +AR.js. Advanced three.js examples are also included. +

+Viewing the AR examples will require a device with a camera and one or both of the Hiro and Kanji marker patterns (either printed or displayed on a second device). +

+Source code hosted at GitHub. + +
+ +
+ + +
Basic Cube
+

A basic scene that superimposes a cube on a Hiro marker. +

+
+ +
+ + +
Many Cubes
+

A scene that superimposes different colored cubes on a Hiro, Kanji, and letter markers. +

+
+ +
+ + +
Smoothed Controls
+

The basic scene, recreated using "smoothed controls", which interpolates the marker location from frame to frame at an adjustable rate. +

+
+ +
+ + +
Image Texture
+

An image is positioned to cover a Hiro marker. +

+
+ +
+ + +
Rotating Globe
+

A rotating globe (illuminated by a point light) is positioned above a Hiro marker. +

+
+ +
+ + +
Video Texture
+

A flat plane, with a video for a texture, is positioned to cover a Hiro marker. +

+
+ +
+ + +
Shader
+

A flat plane moves up and down above a Hiro marker; position and tint color are controlled by vertex and fragment shaders. +

+
+ +
+ + +
Loading 3D Models
+

A 3D model (obj and mtl files) are loaded and displayed above a Hiro marker. +

+
+ +
+ + +
Hole in the Floor (Box)
+

A "hole in the floor" effect. Uses a box geometry to mask the hidden parts of the hole. +

+
+ +
+ + +
Hole in the Floor (Plane)
+

Another "hole in the floor" effect, using a plane geometry to mask the hidden parts of the hole. +

+
+ +
+ + +
Hole in the Floor (Ring)
+

A cylindrical "hole in the floor" effect, using a ring geometry to mask the hidden parts of the hole. +

+
+ +
+ + +
Basic Scene
+

A basic scene created with only Three.js (no AR), useful for prototyping ideas before adding in AR components.

+
+ +
+ + +
Water Effect (no AR)
+

An animated effect (using shaders) that looks like water flowing +out from a central point and being absorbed into the floor. (No AR.)

+
+ +
+ + +
Water Effect (AR version)
+

An animated effect (using shaders) that looks like water flowing +out from a cylindrical hole (displayed above a Hiro marker), and being absorbed into the floor. +
Video preview here.

+
+ +
+ + +
Keyboard-Based Object Movement
+

Move a cube around the screen with the keyboard. Controls (image):
W/A/S/D -- move Forward/Left/Backward/Right (standard),
Q/E -- rotate Left/Right,
R/F -- move Up/Down (think: Rise/Fall),
T/G -- tilt Up/Down (think: look at Tower/Ground).

+
+ +
+ + +
Keyboard-Based Camera Movement
+

Move a camera around the screen with the keyboard.
Uses same controls as Object Movement example.

+
+ +
+ + +
Portal Test
+

Creating a "portal to another world" effect. Camera moves using same controls as Object Movement example. Only visible from one side. +
Not very robust -- see the following portal examples instead.

+
+ +
+ + +
Stencil Buffer Test
+

A simple example that uses layers and the stencil buffer to render part of the scene +onto a plane in the scene. Camera moves using same controls as Object Movement example. Useful for understanding portal view example.

+
+ +
+ + +
Clipping Planes
+

A simple example that sets up a clipping plane (aligned with a plane mesh) to limit the volume of the scene that is rendered. Useful for understanding portal view example.

+
+ +
+ + +
Portal View
+

A "portal to another world" effect. Portal visible through both sides. +
Camera moves using same controls as Object Movement example; also, press 1, 2, or 3 to see the view from different cameras. +
Uses stencil buffer and clipping planes for accurate rendering. +

+
+ +
+ + +
Portal View (AR Version)
+

An augmented reality version of the "portal to another world" effect. Portal renders above a Kanji marker. +
Video preview here.

+
+ +
+ + +
Magic Cube Effect
+

Creates a "magic cube effect" that overlays a cube covered with six AR markers in this pattern. +
Video preview here.

+
+ +
+ + +
Globe with Multiple Markers
+

Similar to the Rotating Globe example: places a globe over a Kanji marker. If Kanji marker is blocked, uses other markers (letter A and letter B) to position the globe.

+
+ +
+ + +
Refraction
+

Creates a rotating torus knot above a Kanji marker. The surface of the knot refracts the scene behind it. +
Video preview here. +

+
+ +
+ + +
Shadow
+

Creates a rotating torus knot above a Kanji marker. The knot casts a shadow onto the plane containing the marker.

+
+ +
+ + +
Shadow Balls
+

Creates four colored bouncing basketballs around a Kanji marker. The balls cast shadows onto the plane containing the marker.

+
+ +
+ + +
Parabolic Path
+

A basketball launches from a Letter-A marker and falls towards a Letter-B marker, following a parabolic path. The ball casts shadows, and a clipping plane (see above example) is used +to make the ball disappear into the marker.

+
+ + + + + + + diff --git a/js/aframe-1.0.4.js b/js/aframe-1.0.4.js new file mode 100644 index 0000000000..5ae86927d5 --- /dev/null +++ b/js/aframe-1.0.4.js @@ -0,0 +1,85141 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.AFRAME = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + for (var i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + +},{}],4:[function(_dereq_,module,exports){ +'use strict'; +// For more information about browser field, check out the browser field at https://github.com/substack/browserify-handbook#browser-field. + +module.exports = { + // Create a tag with optional data attributes + createLink: function(href, attributes) { + var head = document.head || document.getElementsByTagName('head')[0]; + var link = document.createElement('link'); + + link.href = href; + link.rel = 'stylesheet'; + + for (var key in attributes) { + if ( ! attributes.hasOwnProperty(key)) { + continue; + } + var value = attributes[key]; + link.setAttribute('data-' + key, value); + } + + head.appendChild(link); + }, + // Create a