65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Android 和 Intel XDK 探索 Three.js

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2014 年 8 月 5 日

CPOL

11分钟阅读

viewsIcon

32960

downloadIcon

1020

使用 Intel XDK 和 three.js 的 Android 应用 文章 #3

介绍 

本文将介绍如何使用 Intel XDK 和 three.js 开发 Android 应用。它将概述如何使用这个强大的工具为 Android 架构开发基于 GUI 的应用。

背景

对 Android 平台比较陌生

在过去的 15 个月里,我一直在为 Windows 桌面开发应用,所以我对 Android 平台非常陌生。因此,当我探索(对我而言)未知的 Android 世界时,这次经历对我来说是新的。我将涵盖的内容可能不是新鲜事物,但我已经尝试了。

我为什么选择 Intel XDK

我对 HTML 了解不多,我希望使用一个 IDE,我可以在其中运用我的 HTML 技能。整个 IDE 体验对我来说是全新的,因为我以前从未用过 Intel XDK。它是一个基于云的 IDE,在创建分发包的整个过程中,您需要始终连接到互联网。Intel XDK 的**优点**在于您无需配置 Android ADT bundle,并且它内置了模拟器来测试您的应用。在这里,您可以选择不同的设备外形,例如 Google Nexus 4、Google Nexus 7、联想 K900 等。我发现的**缺点**是,如果您长时间使用 IDE,它有时会冻结。这时我不得不重启 IDE,然后重新开始我的工作。*总的来说,我使用 Intel XDK 的体验很好,因为我在开发应用时遇到的麻烦很少。* 

探索 Three.js 

Three.js!事实上,当我搜索网上的一些基于处理的示例时,我发现了它。它本质上是另一个创意编码者的乐趣(http://threejs.org/),它拥有大量由 WebGL 驱动的选项,它在创建精美的 GUI 应用和享受乐趣方面非常有帮助。它是开源的,有大量的示例可供使用。现在有一个问题,当您为 Android 开发时,并非所有浏览器都支持 WebGL。在这种情况下,您需要做的是使用 Canvas 渲染器,这样您就可以继续进行。

什么是 Intel XDK?

Intel XDK 是一个跨平台 IDE,用于在开发环境中开发强大的 HTML 5 应用,并且在连接互联网的情况下可以更新您的代码。构建应用后,您可以将其分发到不同的平台。Android 应用也可以用同样的方式创建,在构建选项中您可以创建 apk。这个 IDE 能够一次编写代码,然后分发到不同的平台。在新的更新的 XDK 中,有一个适用于 Android 的 CROSSWALK 构建选项,目前处于 Beta 阶段,它有助于移植您的原生功能 HTML 5、JavaScript 和 CSS 3 应用。在开发阶段,您可以使用模拟器测试不同外形设备的应用程序。总而言之,这是一个开发 HTML 5 应用并进行分发的绝佳平台 

下载链接 http://xdk-software.intel.com/index.html 

带图的 Intel XDK 下载分步过程 

下一步将检测您的操作系统 

保存文件,exe 文件将被保存。按照以下步骤进行安装和启动 exe 

 下面显示了 Intel XDK 和 Android 项目的项目生命周期 

打开 Intel XDK 后,您将看到一个启动新项目的选项。您可以在此处从空白模板开始,也可以重新使用任何演示并对其进行修改。可用的选项有:

  • i) 从空白项目开始 
  •  ii) 使用演示
  • iii) 导入现有应用:- 您可以在此处移植使用 XDK、PhoneGap 应用、AppMob 应用、HTML 5 API 应用制作的旧应用,但不能移植 Java 应用。
  • iv) 使用 App Starter 它使用 App Framework 2.0。完整详情请访问http://app-framework-software.intel.com/ 
  • v) 从 App Designer 开始 App Designer 允许您使用 App Framework、BootStrap API、jQuery Mobile 或 Top Coat 开始项目。

由于我们的目标是 Three.js,我们将使用演示,特别是 Cross Walk 演示,并通过在 index.html 文件中插入其他代码并添加所需的 three.js 文件来修改演示。Intel 网站上有一个很好的信息,解释并概述了 CrossWalk 运行时http://software.intel.com/en-us/html5/articles/crosswalk-application-runtime 

什么是 Three.js?

Three.js 是一个库,可以非常轻松地在浏览器中实现 WebGL - 3D。虽然用原始 WebGL 创建一个简单的立方体需要数百行 JavaScript 和着色器代码,但 Three.js 的等效代码只有其中一小部分。**Three.js** 是一个轻量级的跨浏览器JavaScript 库/ API,用于在Web 浏览器上创建和显示动画3D 计算机图形。Three.js 脚本可以与 HTML5 canvas 元素SVGWebGL 一起使用 

从头开始

**解码****GITHUB 上的示例并创建一个新的 apk。Three.js 的创始人做得非常出色,所有功劳归于他们,我正在使用其中一个示例来开始。** **https://github.com/mrdoob/three.js/blob/master/examples/canvas_interactive_voxelpainter.html** **

  1. 打开 Intel XDK
  2. 点击项目
  3. 点击启动新项目

点击使用演示

选择 CrossWalk 并点击下一步

 

 点击创建。项目创建后,您将收到一条祝贺消息。

根据您的喜好修改 index.html 页面,它将反映应用的主要更改,并且 
还要添加所需的 JavaScript。

根据您的喜好修改 index.html 页面,它将反映应用的主要更改,并添加所需的 Three.js JavaScript。  

 

近距离查看 index.html 页面 

根据链接:http://aerotwist.com/tutorials/getting-started-with-three-js/

我根据以下描述创建了 index.html 页面的流程,并将在下面进行说明。

让我们看看 Intel XDK 中 index.html 文件的流程 

 

在修改 index.html 文件并向 threejs 文件夹添加所需的 js 文件后(您需要 

从项目的 Windows 目录结构访问文件,然后手动添加文件。在我的例子中,我将文件手动添加到主项目文件夹E:\IntelXDK_Projects\eXAMPLE2\threejs),然后需要点击模拟(您可以从许多可用的模拟器中选择来检查项目)。 

构建过程

这是创建 apk 的主要操作。构建菜单提供了将应用分发到多个平台的所有选项。您可以在此处编辑要添加到应用中的资源和图像。对于 Android,有两个选项: 

  1. Android:- 您可以创建可以分发的普通 APK...   
  2. Android 的 CrossWalk(它处于 Beta 阶段):- 这是一个构建,用于创建一个 CrossWalk 运行时 Android APK,您可以在其中选择为 ARM 设备或 X86 架构进行构建。 

带图的构建过程 

您会看到构建即将完成。您需要点击立即构建应用。

 

下一张图显示了构建过程

您将收到一条构建成功的消息 

整个应用开发过程的改变都发生在 index.html 页面上。在此处的任何更新都会反映更改,并且整个流程都会改变。修改 index.html 页面并包含必要的 Three.js 文件。调整 GITHUB 中的代码将帮助您进行探索。还有一个 CROSSWALK 构建,允许以 x86 或 ARM 架构创建包,它处于 Beta 阶段,但您可以尝试此构建。 

根据链接:- http://aerotwist.com/tutorials/getting-started-with-three-js/

我使用了描述,并以如何在 Intel XDK 中用于创建 Android 应用的方式进行了展示。

index.html 页面的结构(创建新项目) 

对 index.html 所做的任何更改都会反映应用最终的外观。因此,我们需要包含必要的 Three.js 文件,并且整个逻辑都需要在此实现。我深入研究了 three.js GITHUB 存储库,并检查了可以使用的示例,然后将其引入 Intel XDK 并最终从中生成 apk。所以我所做的是分解 index.html 页面及其修改,以提供项目的正确视图。*在学习的背景下,我从 https://github.com/mrdoob/three.js/ 存储库中获得了帮助。它在探索 three.js 方面非常有用。这个库的主要贡献者是 Mr Droob https://github.com/mrdoob 和 theo-armour https://github.com/theo-armour。向这些人致以崇高的敬意(他们在 Three.js 现在的样子方面做得非常出色)*我正在探索这些存储库以进行学习、分享和贡献。 

让我们开始吧 

为了更好地兼容不同的移动平台,我们需要声明 viewport,并设置 device-width height。 

设备宽度允许根据不断变化的设备进行调整,无论是平板电脑还是不同模式的手机。

声明  

<meta name="viewport" width, user-scalable=no, minimum-scale=1.0, max content="width=device-imum-scale=1.0">

这也意味着当我们改变设备的朝向时,它能提供对应用的正确访问 

样式标签

样式标签允许控制应用在设备上的渲染方式。这是显示应用外观的修改。因此,现在对于这个项目,我们将相应地修改样式标签 

               <style>
			body {
				font-family: Monospace;
				background-color: #f0f0f0;
				margin: 0px;
				overflow: hidden;
			}
		</style>

为了方便重新加载,避免反复重新加载页面,我们将 three.min.js 包含在 html 的 head 标签中,并将脚本包含在 script 标签中。

<script></script>

当我们把 three.js 脚本标签包含在 body 中时,我们就允许重要的操作在 three.min.js 脚本中执行。这里是实现 three.js 的逻辑所在,因此我们需要将其包含在 head 标签中。 

现在轮到初始化变量,或者实现 3D GUI 结构的行为方式,我们实现诸如对象移动、交互、靠近对象或移出对象等动画,我们通过调用 init() 方法开始。

在 three.js 脚本的入口点,我们需要附加元素和子行为。为了使 Geometry 生效,我们需要在此处实现变量及其实现逻辑。 

当我们看到 Three.js 脚本时,我们发现它本质上是涉及 3D GUI 描绘的:

  1. 场景
  2. 摄像头
  3. 投影仪
  4. 渲染器和对象。

Three.js 脚本中的一些修改允许实现平面 Geometry 到法线,我们使用 var normalMatrix= new Three.Matrix3(); 

要创建相机透视的阴影效果,我们使用此

camera= new THREE.perspectiveCamera();  修改自定义网格涉及 Geometry 的更改,因此我们执行以下操作:

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 );

我们使用投影仪来改变对象的行为,并实现鼠标移动和选择特定对象。这也有助于在屏幕空间中进行投影。

这里的代码行控制着光线反射和环境光效果。这也显示了灯光效果会是什么样的。

//
// var ambientLight = new THREE.AmbientLight( 0x606060 );
//

查看变量声明

 target=new THREE.Vector3(0,200,0);

在上面的声明中,我们声明了一个 3D 向量。3D 向量通常是一个具有大小和方向的几何量。

var normalMatrix=new THREE.Matrix 3();

这是一个 3*3 矩阵。

为了投影目的,我们使用鼠标 2D 和鼠标 3D。

更多修改和整个 html 代码如下所示,它创建了一个网格,您可以放置方块并进行设计。这是摘录自 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();
 
				// 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>

项目在模拟器中的外观

 

实验后,我们发现向 index.html 添加简单的修改并添加所需的 three.js 文件可以为您提供一些您可以在项目中使用得很酷的 GUI 效果。

  • three.js 的可能性是无限的,您也可以用它来开发游戏。
  • Three.js 是一个出色的 WebGL 工具,可帮助您以创新的方式探索 3D GUI 应用程序。

现在,当您结合 Intel XDK IDE 时,您可以用它创建一些很棒的 APK。

Nexus7 模拟器图片

本文旨在展示如何使用 Intel XDK IDE 开发基于 WebGL 的精美 GUI Android 应用 Three.js。整个项目过程需要互联网连接。随着我学习的深入,我将尝试做出更多贡献。Three.js 的 GITHUB 存储库https://github.com/mrdoob/three.js 检查示例并进行实验。我喜欢调整代码。

参考文献

 优质资源 

您将在 StackOverflow 上关于 Three.js 的问题中了解到很多东西,并获得良好的知识。

http://stackoverflow.com/search?q=Three.js 

Intel XDK 文档

http://software.intel.com/en-us/html5/articles/xdkdocs  

Three.js 文档

http://threejs.org/docs/   

关注点

我花了大量时间学习 three.js 和 Intel XDK,这是我分享所学知识的唯一机会,因此写了这篇文章。Intel XDK 是一个非常有用的工具,用于为 Android 和其他架构构建 HTML 5 应用。Intel 还包含一个用于创建 WebGL 基于 Android 项目和其他针对 Android 的构建的 CrossWalk Android Beta 构建。

历史

第一篇文章已更新代码和 APK 

© . All rights reserved.