Introduction
This article is about developing android apps using Intel XDK and three.js.It will give an overview on how to develop GUI based app for Android architecture using this wonderful tool.
Background
Pretty new to Android Platform
For last 15 months i have been developing apps for Windows Desktop and so i am very new to Android platform. So this experience will be new for me as I explore the unknown world(for me) of Android .The things that i cover might not be new but i have given it a try
Why i have chosen Intel XDK
I have little knowledge of HTML and i intend to use an IDE where i can implement my HTML skills. The whole IDE experience was a new one for me because i have not used Intel XDK once. It's a cloud based IDE which requires you to be always connected to the internet when you go through the entire process of creating a package for distribution. Pluses for Intel XDK would be that you don't have to configure Android ADT bundle and it has got an inbuilt emulator to test your app. Here you have the options to choose from different form factors such as Google Nexus 4 and Google Nexus 7,Lenovo K900 etc. Minuses i found would be that the IDE used to freeze at times if you used to work for on it for a long time. At these times i had to restart the IDE and then start my work again. Overall my experience using Intel XDK was good one because i had little trouble developing my app.
Exploring Three.js
Three.js!! in fact it came to my liking as i was searching some processing based examples on net. Essentially another Creative Coders delight(http://threejs.org/) it has got lot of options powered by WebGL it is essentially helpful in creating great looking GUI apps and have fun with. Being Open Sourced with lot of examples to work with. Now one catch as you are developing for Android not all browsers support WebGL in that case what you need to do is use Canvas renderer and you are on your way.
What is Intel XDK?
The Intel XDK is cross platform IDE for developing solid HTML 5 in the developing environment and you can update your code being connected to internet. After you build the app you can distribute it to different platforms. Android apps can be created by the same way and in the build option you can create the apk.This IDE has the ability to code once and distribute it to different platforms. In the new updated XDK there is CROSSWALK build option for Android that is in Beta phase right now it helps in porting your native capabilities html 5 ,JavaScript and CSS 3 apps. During Development phase you can test the app for different form factors using the emulator. All in all it's a great platform to develop HTML 5 apps and distribute it
Download Link http://xdk-software.intel.com/index.html
Step by step process of downloading Intel XDK with figures
The next step will detect your OS
Save the File and the exe will be saved. Follow the steps as mentioned below to install and start the exe
The project lifecycle of Intel XDK and Android Project shown below
When you open up Intel XDK you will be presented with an option to Start a new project. Here you can start a fresh with a blank template or reuse any demo and modify it. The options that are available are
- i)Start with a Blank Project
- ii)Work with a Demo
- iii)Import an existing app :-here you can port old apps made with the XDK's,PhoneGap apps,AppMobapps,HTML 5 api based apps but cannot port Java apps.
- iv)Use App Starter It uses App Framework 2.0 .Full details are available here http://app-framework-software.intel.com/
- v)Start with App Designer App Designer allows you to get going with the project using App Framework,BootStrap API,jQuery Mobile or Top Coat.
As we are targeting Three.js we will use work with a demo that too the Cross Walk Demo and modify the Demo inserting additional codes in the index.html file and adding the required three.js files.There is a great information explaining and giving an overview into CrossWalk runtime in the Intel Website http://software.intel.com/en-us/html5/articles/crosswalk-application-runtime
What is Three.js?
Three.js is a library that makes WebGL - 3D in the browser - very easy. While a simple cube in raw WebGL would turn out hundreds of lines of JavaScript and shader code, a Three.js equivalent is only a fraction of that. Three.js is a lightweight cross-browser JavaScript library/API used to create and display animated 3D computer graphics on a Web browser.Three.js scripts may be used in conjunction with the HTML5 canvas element, SVG or WebGL
Starting A fresh
Decoding one of the examples and creating a new apk from the GITHUB.The Founders of Three.js have done an excellent job with all credits to them i am using one of the examples to get going. https://github.com/mrdoob/three.js/blob/master/examples/canvas_interactive_voxelpainter.html
- Open Intel XDK
- Click on Project
- Click on Start a new Project
Click on Work with a demo
Select CrossWalk and click on next
Click on Create.As the project is created you will get a Congratulation message
According to your liking change the index.html page as it will reflect the main changes in the app and
also add the JavaScript required.
According to your liking change the index.html page as it will reflect the main changes in the app and also add the Three.js JavaScript required.
A Close look at the index.html page
According to the link:-http://aerotwist.com/tutorials/getting-started-with-three-js/
I have come up with a flow of index.html page and it is described below
Let's see the flow of the index.html file within Intel XDK
After the changes in the index.html file and adding the required js files in the threejs folder(You need
to access the files from the Windows directory structure of the project and then add the files manually. In my case i add the files manually over to the main project folder E:\IntelXDK_Projects\eXAMPLE2\threejs) you need to click on emulate(you can choose from the many emulators available to check the project)
The Build process
Here lies the main action where the apk's are created.The Build menu has all the options to distribute the apps in multiple platforms.Here you can edit Asset as well as images that you want to add to the app.For Android there are two options
- Android :- you create the normal APK's that you can distribute...
- CrossWalk for Android (it's in Beta phase) :-this is a build that creates a CrossWalk Runtime Android APK where you have the options to build it for ARM based devices or X86 architecture.
The Build process with figures
You will see that the build is about to be created.You need to click on build app now
The next figure shows the build process
You will get a message that build is successful
The Whole process of changing the app development process happens at the index.html page.Any update here reflects the change and whole flow changes.Make changes to the index.html pages and include the necessary Three.js files.Tweaking the code from the GITHUB will help you explore.There is also a CROSSWALK build which allows to create the package in x86 or ARM architecture it's in beta phase but you can try this build.
According to the Link:- http://aerotwist.com/tutorials/getting-started-with-three-js/
I have used the description and showed it in terms how it works in Intel XDK for creating an Android app
The anatomy of the index.html page(Creating a new Project)
Any change made to the index.htmlactually reflects how the app will look like finally.So we need includenecassry Three.js files as well as the whole logic needs to be implementedhere.I dug deep in to the three.js GITHUB repository and check which are the examples that can be worked upon and bring it to Intel XDK and finally make the apk out of it.So what i have done is broken down the index.html page and its modification to give the proper view of the project.In context of learning i have taken help from the https://github.com/mrdoob/three.js/ repository.It's very useful in exploring the three.js.The primary contributor to this library is Mr Droob https://github.com/mrdoob and theo-armour https://github.com/theo-armour. Due respect to these people(They have done excellent job in what Three.js is now) i am exporing these repositories to learn,share and contribute.
let's Start
To be more compatible with different mobile platforms we need to declare viewport with device- width height.
The device width allows adjustment according to the changing devices be it a tablet or different mode phones.
The declaration
<meta name="viewport" width, user-scalable=no, minimum-scale=1.0, max content="width=device-imum-scale=1.0">
This also implies that when we change the orientation of the device it gives a proper access of the app
The Style Tag
The Style Tag allows how the app is rendered to the devices.Here is the modification that shows how the app will look like.So now for this project we modify the Style tag accordingly
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
For reloading to make easier so that we have to reload the pages again and again we include three.min.js within the head tag of the html including the script in the script tag
<script></script>
As we include the three.js script tag in the body we allow important actions to execute within the three.min.js script.Here in lies the logic of implementing the three.js and hence we need toinclude it to the head tag.
Now comes the turn for intilaizatioof the variables or getting to implement the way the 3D GUI structurewill behave we implement animations susch as object movements interactions getting in closer to the objects or moving out we start by calling the init() method.
In the entry point for three.js script we need to append Element and the chid behaviours.For getting Geometry to work we need to implement variables and their implementation logic here.
As we come across Three.js Script we see that it is essentially a 3D gui depiction involving
- Scenes
- Cameras
- Projectors
- Renderers and Objects.
Certain modifications we have in Three.js script allows implementing plane Geometry to Face normals we use var normalMatrix= new Three.Matrix3();
For creating a Shadow effect with the camera perspective we use this
camera= new THREE.perspectiveCamera();
Modifying the Custom grid involves changes in the Geometry hence we do the following
var size = 500, step = 50;
var geometry = new THREE.Geometry();
for ( var i = - size; i <= size; i += step ) {
geometry.vertices.push( new THREE.Vector3( - size, 0, i ) );
geometry.vertices.push( new THREE.Vector3( size, 0, i ) );
geometry.vertices.push( new THREE.Vector3( i, 0, - size ) );
geometry.vertices.push( new THREE.Vector3( i, 0, size ) );
}
var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } );
var line = new THREE.Line( geometry, material );
line.type = THREE.LinePieces;
scene.add( line );
We use projector to change the behavior of the objects and also implementing mouse movements and to select certain objects. This also helps in projection in a screen space.
The light reflection as well as ambient light effect is controlled in these lines of code.This also shows how the lighting effect will be.
//
// var ambientLight = new THREE.AmbientLight( 0x606060 );
//
Taking a look at variable declaration
target=new THREE.Vector3(0,200,0);
In this declaration above we declare a 3D vector.A 3D vector is in general a geometric quantity that has magnitude and direction
var normalMatrix=new THREE.Matrix 3();
It's a 3*3 matrix.
For projection purpose we use mouse 2D and mouse 3D
More modifications and the whole code of the html is shown below it create a grid and you can place the boxes and design it. This is an excrept modified from the https://github.com/mrdoob/three.js/
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js canvas - interactive - voxel painter</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="../build/three.min.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
var projector, plane;
var mouse2D, mouse3D, raycaster, theta = 45,
isShiftDown = false, isCtrlDown = false,
target = new THREE.Vector3( 0, 200, 0 );
var normalMatrix = new THREE.Matrix3();
var ROLLOVERED;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js</a> - voxel painter<br><strong>click</strong>: add voxel, <strong>control + click</strong>: remove voxel, <strong>shift</strong>: rotate, <a href="javascript:save()">save .png</a>';
container.appendChild( info );
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.y = 800;
scene = new THREE.Scene();
var size = 500, step = 50;
var geometry = new THREE.Geometry();
for ( var i = - size; i <= size; i += step ) {
geometry.vertices.push( new THREE.Vector3( - size, 0, i ) );
geometry.vertices.push( new THREE.Vector3( size, 0, i ) );
geometry.vertices.push( new THREE.Vector3( i, 0, - size ) );
geometry.vertices.push( new THREE.Vector3( i, 0, size ) );
}
var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } );
var line = new THREE.Line( geometry, material );
line.type = THREE.LinePieces;
scene.add( line );
projector = new THREE.Projector();
plane = new THREE.Mesh( new THREE.PlaneGeometry( 1000, 1000 ), new THREE.MeshBasicMaterial() );
plane.rotation.x = - Math.PI / 2;
plane.visible = false;
scene.add( plane );
mouse2D = new THREE.Vector3( 0, 10000, 0.5 );
var ambientLight = new THREE.AmbientLight( 0x606060 );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
directionalLight.position.normalize();
scene.add( directionalLight );
var directionalLight = new THREE.DirectionalLight( 0x808080 );
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
directionalLight.position.normalize();
scene.add( directionalLight );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild(renderer.domElement);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'keydown', onDocumentKeyDown, false );
document.addEventListener( 'keyup', onDocumentKeyUp, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse2D.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse2D.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
var intersects = raycaster.intersectObjects( scene.children );
if ( intersects.length > 0 ) {
if ( ROLLOVERED ) ROLLOVERED.color.setHex( 0x00ff80 );
ROLLOVERED = intersects[ 0 ].face;
ROLLOVERED.color.setHex( 0xff8000 )
}
}
function onDocumentMouseDown( event ) {
event.preventDefault();
var intersects = raycaster.intersectObjects( scene.children );
if ( intersects.length > 0 ) {
var intersect = intersects[ 0 ];
if ( isCtrlDown ) {
if ( intersect.object != plane ) {
scene.remove( intersect.object );
}
} else {
normalMatrix.getNormalMatrix( intersect.object.matrixWorld );
var normal = intersect.face.normal.clone();
normal.applyMatrix3( normalMatrix ).normalize();
var position = new THREE.Vector3().addVectors( intersect.point, normal );
var geometry = new THREE.CubeGeometry( 50, 50, 50 );
for ( var i = 0; i < geometry.faces.length; i ++ ) {
geometry.faces[ i ].color.setHex( 0x00ff80 );
}
var material = new THREE.MeshLambertMaterial( { vertexColors: THREE.FaceColors } );
var voxel = new THREE.Mesh( geometry, material );
voxel.position.x = Math.floor( position.x / 50 ) * 50 + 25;
voxel.position.y = Math.floor( position.y / 50 ) * 50 + 25;
voxel.position.z = Math.floor( position.z / 50 ) * 50 + 25;
voxel.matrixAutoUpdate = false;
voxel.updateMatrix();
scene.add( voxel );
}
}
}
function onDocumentKeyDown( event ) {
switch( event.keyCode ) {
case 16: isShiftDown = true; break;
case 17: isCtrlDown = true; break;
}
}
function onDocumentKeyUp( event ) {
switch( event.keyCode ) {
case 16: isShiftDown = false; break;
case 17: isCtrlDown = false; break;
}
}
function save() {
window.open( renderer.domElement.toDataURL('image/png'), 'mywindow' );
return false;
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
if ( isShiftDown ) {
theta += mouse2D.x * 3;
}
camera.position.x = 1400 * Math.sin( theta * Math.PI / 360 );
camera.position.z = 1400 * Math.cos( theta * Math.PI / 360 );
camera.lookAt( target );
raycaster = projector.pickingRay( mouse2D.clone(), camera );
renderer.render( scene, camera );
}
</script>
</body>
</html>
The project as it looks in the emulator
After the experiment we see that adding simple modification to the index.html and adding required three.js files givesyou some cool gui effects that yo can use in your projects.
- The possibilities are endless with three.js as you can also develop games with it.
- Three.js is an excellent WebGL tool that helps you explore 3D GUI applications in an innovative manner.
Now when you combine the Intel XDK IDE you can get some great APK's created with it.
Nexus7 Emulator Images
This article is an attempt to showcase how Three.js can be develop good GUI based WebGL Android app using Intel XDK IDE.For the entire project process Internet connectivity is required.As i learn more i will try to contribute more. GITHUB repository for Three.js https://github.com/mrdoob/three.js Check the examples and experiment. I had fun tweaking the codes.
References
Good resources
You will Know a lot and get good knowledge out of questions of Three.js at StackOverflow
http://stackoverflow.com/search?q=Three.js
Intel XDK Documentation
http://software.intel.com/en-us/html5/articles/xdkdocs
Three.js documentation
http://threejs.org/docs/
Points of Interest
I have been putting in lots of time studying three.js and Intel XDK and this was the only opportunity to share what i have learned hence the article.The Intel XDK is very useful tool for building HTML 5 apps for Android as well as other architecture.The Intel also contains a build for the CrossWalk Android beta build for creating WebGl based Android projects and other Android targeted build
History
First Article updated with Codes and the APK's