Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / Android

Discovering Three.js with Android and Intel XDK

5.00/5 (5 votes)
5 Aug 2014CPOL11 min read 32.1K   911  
Android app using Intel XDK and three.js Article #3

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
Image 1

The next step will detect your OS 

Image 2

Save the File and the exe will be saved. Follow the steps as mentioned below to install and start the exe

Image 3

 The project lifecycle of Intel XDK and Android Project shown below

Image 4

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  

  1. Open Intel XDK
  2. Click on Project
  3. Click on Start a new Project

Image 5

Click on Work with a demo

Image 6

Select CrossWalk and click on next

Image 7

Image 8 

 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.

Image 9

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.  

Image 10 

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

Image 11 

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  

  1. Android :-  you create the normal APK's that you can distribute...   
  2. 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

Image 12 

The next figure shows the build process

Image 13

You will get a message that build is successful 

Image 14

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  

HTML
<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 

HTML
       <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

  1. Scenes
  2. Cameras
  3. Projectors
  4. 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

HTML
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.

HTML
//
// 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/

HTML
 <!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();
 
				// Grid
 
				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 );
 
				// Lights
 
				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

Image 15 

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

Image 16

Image 17

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  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)