A Rubik's cube in WebAR
Introduction
Augmented Reality or AR can simply be defined as the integration of a live video stream with some computer generated graphics. One example, that could come into mind is the microsoft hololens demo. The concept behind it is to take a picture and render some 3D or 2D graphics on to it.
In the current mobile browser like Google Chrome and Mozilla Firefox, we can render graphics and animation on the screen using a HTML5 canvas, and also develop games that are not based on Flash and do not require any additional plugins. This can be done using a framework/API known as WebGL(Web Graphics Library), which is based on the OpenGL ES 2.0. In this tutorial, we will be using some amazing javascript libraries that in-turn use this WebGL API, to create a rubik’s cube in Augmented Reality on the mobile browser.
Prerequisites
For this tutorial, you would need to have some background knowledge on how to write programs in HTML, CSS, and Javascript. In addition to that, it is recommended to learn on how to use the following libraries :
-
Three.js : Three.js is a library that makes WebGL easy to use. It comes with a lot of features similar to any 3D graphics application(for example Blender, Maya, 3Ds Max) like Lights, Cameras, Textures, Materials, Geometries, etc. A good starting point to learn about this library is here.
-
Awe.js : A small library that allows us to create Augmented Reality applications quickly and easily. With this library, we can do Marker-based AR and Location-Based AR applications. Check out this link for the tutorial on how to use this library.
Other than the tutorials, you would need few other things to get started :
- Clone/Download the Awe.js project to your local computer using the following command :
git clone https://github.com/buildar/awe.js.git
This is the base project that we will be editing and adding code to.
- I have modified the base version of the awe.js file, so that we can add different colors for each face of the cube. Download this file from this link, and save it to the
js
directory.
For this tutorial, the application that we will be developing is a marker based AR application. So, we will solely be focusing on the examples/marker_ar
directory.
Base Code
Before we start, here is an idea on how the base project works. When you open examples/marker_ar/index.html
in the browser (assuming a http server is setup and files are served locally) of your mobile device, it will open your device’s camera and display live video stream. When we focus the camera on a marker(in this case, the examples/marker_ar/64.png
), it will render a cube with a texture on it. It would look something like this :
Screenshot taken from Chrome browser on a Moto G 2nd gen
The working of this code (in index.html
) is as follows:
- Awe.js is initialized with the default settings.
...
window.addEventListener('load', function() { // When the page loads
window.awe.init({ // Initialize Awe.js
device_type: awe.AUTO_DETECT_DEVICE_TYPE, // Detect Device type
settings: { // Default settings
container_id: 'container',
default_camera_position: { x:0, y:0, z:0 },
default_lights:[
{
id: 'point_light',
type: 'point',
color: 0xFFFFFF,
},
],
},
...
- After it is initialized completely, various dependencies are loaded.
...
ready: function() { // After initialized and ready
awe.util.require([ // Load dependecies and capabilities
{
capabilities: ['gum','webgl'],
files: [
[ '../../js/awe-standard-dependencies.js', '../../js/awe-standard.js'],
'awe-jsartoolkit-dependencies.js',
'awe.marker_ar.js',
],
...
- Upon loading the dependencies, a Three.js scene is setup using Awe.js API.
...
success: function() { // After successfully loading the dependecies
awe.setup_scene(); // setup the basic three.js scene
...
- A point of interest (poi) and a cube with a texture is added to the scene.
...
awe.pois.add({ id:'poi_1', position: { x:0, y:0, z:10000 }, visible: false }); // Add a point of interest
awe.projections.add({ // Add a projection, i.e the cube
id:'projection_1',
geometry: { shape: 'cube', x:120, y:120, z:120 },
material:{ type: 'phong', color: 0xFFFFFF },
texture: { path: 'awe_by_buildAR.png' },
}, { poi_id: 'poi_1' }); // link the projection with the poi
...
- Marker tracking is handled using the point of interest (the cube is projected according to the poi’s position, orientation based on the marker).
...
awe.events.add([{ // Add an event handler
id: 'ar_tracking_marker',
device_types: { // target the devices that are available
pc: 1,
android: 1
},
register: function(handler) { // Handle the event only when the marker is visible
window.addEventListener('ar_tracking_marker', handler, false);
},
unregister: function(handler) {
window.removeEventListener('ar_tracking_marker', handler, false);
},
handler: function(event) { // main functionality for the event handler
if (event.detail) {
if (event.detail['64']) { // pre-defined set of markers, we are using marker 64
awe.pois.update({ // Update the position of the poi only when the marker is visible
data: {
visible: true,
position: { x:0, y:0, z:0 },
matrix: event.detail['64'].transform
},
where: {
id: 'poi_1'
}
});
}
else { // else hide the projection
awe.pois.update({
data: {
visible: false
},
where: {
id: 'poi_1'
}
});
}
...
- Scene is rendered.
The Concept
The concept to render the rubik’s cube is like this:
- The colors of each
cubit
(An individual cube in the rubik’s cube) are defined. - 27 small cubits are added to the scene in the same way as given in the base code using a loop.
- All the cubits have the a single point of interest in common.
- The colors are then mapped to the cubits using a
MeshFaceMaterial
.
The Program
The result that you are going to see when you open the webpage in the browser is going to be something like this:
Screenshots taken from Chrome browser on a Moto G 2nd gen
Conclusion
So we basically created a rubiks cube model in AR on the Mobile Browser. The results can vary from device to device, and it also depends on how much processing power your device has. For example, A nexus phone would render the page faster and better then the Moto g 2nd gen. I hope you guys have learned something in this tutorial and have fun experimenting with this. Links to the project are given below, please do check it out. I will be uploading another tutorial on how to animate the cube and give controls to the user to play with it in the near future.
Update 1 : To my understanding, the awe.js seemed to be dead and was not under active development, but now they restarted the project and hopefully we see some new features. So I’ll be doing a new tutorial on the rubik’s cube creation and game design depending how active the library is developed. Please stay tuned and thank you.
Resources
- Three.js : http://www.threejs.org
- Awe.js : https://buildar.com/awe/tutorials/intro_to_awe.js/index.html
- Rubiks cube color scheme : http://ruwix.com/pics/western-color-scheme-rubiks-cube.jpg
- Project page : https://gitlab.com/dvenkatsagar/rubikAR
- Working example : https://dvenkatsagar.github.io/proj/rubikAR/
- Marker Image : https://dvenkatsagar.github.io/proj/rubikAR/64.png
I feedback.
Let me know what you think of this article on twitter @dvenkatsagar or leave a comment below!