Try Out Our Mobile Game

A Multi Galaxy Space Adventure Game

s f

Contact Info
198 West 21th Street, Suite 721
New York, NY 10010
youremail@yourdomain.com
+88 (0) 101 0000 000
Follow Us

Web AR using AR.js – Deep Dive

If we are to create a web Augmented Reality experience, we could use AR.js, which helps us create quick AR experiences, backed up by its AR Toolkit support.

Pre-requisites develop our own AR experiences are,

  • Good understanding of Java Script.
  • Good understanding of HTML.
  • Good understanding of how Augmented Reality work, specifically knowing what is a marker based solution.
  • Good understanding of using Inspector tool.

Before we start off, make sure you have the following handy,

Over the course of this tutorial, we will be looking in detail into the following frameworks and building an experience such that we display a 3D content with audio playback upon scanning a marker. Towards the end, we will also be looking at user interfaces in Web AR.

  • AR.js
  • A-Frame

For 3D content, we will be using Sketch fab. https://sketchfab.com/

Let’s get on to business

As a first step, lets create a folder in htdocs (inside XAMPP folder), naming it as ‘ardemo’.

Then open sublime text, drag and drop this folder.

Create a file with the following code and save it as ‘index.html’

<!DOCTYPE html>
<html>
    <script src="js/aframe-v0.8.2.min.js"></script>
    <script src="js/aframe-ar.js"></script>
<body style="margin : 0px; overflow: hidden;">
</body>
</html>

Looking at this code, you will see couple of js files included in the header part. These are files that expose components required to build an experience on top of AR.js. With AR.js, there are two ways to develop experiences,

A. Plain JavaScript using components of AR.js.

B. A-Frame (A quick and easier way)

As part of this tutorial we will be using A-Frame. A-Frame lets us create a 3D scene graph using its vast component collections, wherein we can use this scene graph along with AR.js custom A-Frame components to create quick and easy AR experiences. A-Frame uses a HTML like markup language, hence making it easy for developers who are familiar with HTML.

To know more about A-Frame, visit documentation

You can clone the following Git repositories to have both a-frame and a-frame-ar.js residing in your server. This will be the best approach as you can keep pulling the changes that are being made on a regular basis by contributors.

https://github.com/aframevr/aframe

https://github.com/jeromeetienne/AR.js

In order to use additional features in your project, you also need to have extras, utility components such as animations support, audio visualizer etc.
https://github.com/donmccurdy/aframe-extras

Once all these three are ready, create a folder names ‘js’ in your project and copy the following files,

• Now let’s start creating a scene and also add a marker to the scene. Use the following code in your index.html file,

<body style="margin : 0px; overflow: hidden;">
    <a-scene embedded arjs='trackingMethod: best; patternRatio: 0.9; debugUIEnabled: false; maxDetectionRate:30;' antialias="true">
    <a-marker emitevents="true" id="logo-marker" type="pattern" url="markers/pattern-marker.patt" cursor="rayOrigin: mouse" markerhandler>
    </a-marker>
    </a-scene>
</body>

This code will add a scene with attributes to define it as an ar.js scene. There is also a marker tag that lets us specify a custom maker.

Let’s take an image like the following and go to the following link to create a ARToolKit maker,

https://jeromeetienne.github.io/AR.js/three.js/examples/marker-training/examples/generator.html>

Use the image as above and specify a ration as high as 0.9 so that you see lesser black border. If you see the code, you will need to set a ratio that you choose to set while creating the custom marker.

Follow the instructions and download both the marker file and marker image (converted into specifications that the tool kit understands). So do not scan the image that you used in the process, rather the image that the toolkit training page generates.

Let’s go back to the project and create another folder called marker and paste the image and marker that was generated.

Download the following 3D model (gltf format) which is a straight forward support in A-Frame as against FBX, which needs quite a few additional procedures. We will do this as a separate topic during the coming months.

https://sketchfab.com/models/787d59c3deb047b99093e7a270e9c8bf

Create a folder ‘assets’ and move the extracted files there. Then, get the sound from here, and put it on to the same folder.

Then comes the interesting part to explore more on a-frame components,

<a-assets>
    <audio id="roar_sound" src="assets/dino.mp3" response-type="arraybuffer"></audio>
    <a-asset-item id="dino" src="assets/scene.gltf"></a-asset-item>
</a-assets>

The assets tag helps us define the assets that we need to use in the scene. These components are the ones that can be queried through scripting through their ids and manipulated using properties. You will see more of their properties and how to access as we move on to scripting.

Having defined the assets lets add them under the marker tag, defining them as augmented objects. A-frame entity which is a place holder to plugin or attach components.

<a-marker emitevents="true" id="logo-marker" type="pattern" url="markers/pattern-marker.patt" cursor="rayOrigin: mouse" markerhandler>
    <a-entity id="animated-dino" gltf-model="#dino"
        position="0 0 0"
        rotation="0 0 0"
        scale="0.001 0.001 0.001"
        crossOrigin="anonymous"
        dinoInteractionListener>
    </a-entity>
    <a-entity sound="src: #roar_sound; volume: 1; loop: true">
    </a-entity>
</a-marker>       

Most common attributes that we would need to set while scripting would be position and scale of the object such that they look nice on AR. Note that we have linked components using their id defined in the a-assets portion.

https://aframe.io/docs/0.8.0/core/entity.html Add a source of light to the whole scene to make it bright (inside the scene),

<a-entity id="point_light_1" light="type: point; intensity: 5.1;" position="0 0 0"></a-entity>

Finally, add a camera to the scene that renders the objects for us. You may set properties such as near and far plane based on the results you see on device when you move the phone away from the target.

<a-entity camera="active: true; near: 1; far: 1000;"
    position="0 0 0"
    cursor="rayOrigin: mouse"
    data-aframe-default-camera>
</a-entity>

At this point, we are ready to see the object on AR. Start XAMPP and hit the url, https://xxxx/ardemo
“https” is key here since we use device camera, we will need a secure hosting.

Good job! You are done with the first part.


The second part is all code and mostly of you will easily understand this since it’s all java script!
If you see the above code, we disabled auto play sound and also did not specify animation.
Let’s do it now, create a file ‘touchme.js’, and paste the following code.


The second part is all code and mostly of you will easily understand this since it’s all java script!
If you see the above code, we disabled auto play sound and also did not specify animation.
Let’s do it now, create a file ‘touchme.js’, and paste the following code.

var soundentity = null;
var isTargetFound = false;
var interacted = false;
var dino = null;

AFRAME.registerComponent("markerhandler", {
    init: function () {
        console.log('markerhandler-init');

        markerObj = document.querySelector('a-marker');
        markerObj.hidden = true;

        soundentity = document.querySelector('[sound]');

        dino = document.querySelector('#animated-dino');
        dino.object3D.visible = false;

        //dino.setAttribute('animation-mixer', {clip: 'C4D Animation Take', loop: 'repeat'});
    },

    tick: function () {

        if (markerObj != null) {
            if (markerObj.object3D.visible == true) {
                if (isTargetFound)
                    return;

                isTargetFound = true;
                console.log("marker visible");
                document.getElementById("banner-section").style.display = "none";

                dino.object3D.visible = true;
                if (interacted) {
                    soundentity.components.sound.playSound();
                    dino.setAttribute('animation-mixer', {
                        clip: 'C4D Animation Take',
                        loop: 'repeat'
                    });
                }

            } else {
                if (!isTargetFound)
                    return;

                isTargetFound = false;
                console.log("marker invisible");
                document.getElementById("banner-section").style.display = "block";

                dino.object3D.visible = false;
                if (interacted) {
                    soundentity.components.sound.stopSound();
                }

            }
        }
    }
});

AFRAME.registerComponent('dinoInteractionListener', {
    init: function () {
        if (dino == null)
            dino = document.querySelector('#animated-dino');
        dino.addEventListener('mousedown', function (ev) {
            console.log('touched at - ', ev.detail.intersection.object);
            interacted = true;

            soundentity.components.sound.playSound();
            dino.setAttribute('animation-mixer', {
                clip: 'C4D Animation Take',
                loop: 'repeat'
            });
        });
    }
});

Looking at the code, you have two major functions

A. markerhandler

This function initializes few variables that you would be needed in cases where the user goes on and off target. You will also need these to start sound and animate the model when user touches the model.
By neither default the models do not animate nor the sounds play as we have not set the properties in the mark up tags, rather we have controlled it through scripting.

B. dinoInteractionListener

This function adds a touch listener to the model and whenever there is touch actions are performed as defined the code in the block.

Lastly, we shall add a message to user to indicate when user goes off target; using some styles and a div tag in the scene tag. Find this way out for user interface was a bit tricky and took some time to get going since a-scene pushes a set of styles which sit on top of the page. Had to sit for a day to figure this out and come up with a solution.

Create a style under folder ‘styles’ and add this style.

.banner-section {
    position: absolute;
    top: 250px;
    width: 100%;
    text-align: center;
    z-index: 1;
    color: grey;
    display: block;
    height: 850px;
    margin: 0 auto;
    text-align: center;

}

Cool! So that it run the page on your mobile browser and now say you know WEB AR!


Post a Comment