summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorgman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-10 23:14:53 +0000
committergman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-10 23:14:53 +0000
commita6974dc7ec62727d5edbbad9b49c052005e5193f (patch)
tree664297499f44a249d9684a33796be1a35926f0b4 /o3d
parent24a4d10647ee76bae3d977caba9e8b13b5b81cf4 (diff)
downloadchromium_src-a6974dc7ec62727d5edbbad9b49c052005e5193f.zip
chromium_src-a6974dc7ec62727d5edbbad9b49c052005e5193f.tar.gz
chromium_src-a6974dc7ec62727d5edbbad9b49c052005e5193f.tar.bz2
Add Google IO sample.
Review URL: http://codereview.chromium.org/149438 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20437 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/DEPS2
-rw-r--r--o3d/DEPS_gyp2
-rw-r--r--o3d/samples/GoogleIO-2009/assets/colorbar.pngbin0 -> 1977 bytes
-rw-r--r--o3d/samples/GoogleIO-2009/assets/style.css8
-rw-r--r--o3d/samples/GoogleIO-2009/shaders/checker.shader111
-rw-r--r--o3d/samples/GoogleIO-2009/step01.html176
-rw-r--r--o3d/samples/GoogleIO-2009/step02.html206
-rw-r--r--o3d/samples/GoogleIO-2009/step03.html254
-rw-r--r--o3d/samples/GoogleIO-2009/step04.html264
-rw-r--r--o3d/samples/GoogleIO-2009/step05.html292
-rw-r--r--o3d/samples/GoogleIO-2009/step06.html301
-rw-r--r--o3d/samples/GoogleIO-2009/step07.html302
-rw-r--r--o3d/samples/GoogleIO-2009/step08.html330
-rw-r--r--o3d/samples/GoogleIO-2009/step09.html358
-rw-r--r--o3d/samples/GoogleIO-2009/step10.html361
-rw-r--r--o3d/samples/GoogleIO-2009/step11.html365
-rw-r--r--o3d/samples/GoogleIO-2009/step12.html394
-rw-r--r--o3d/samples/GoogleIO-2009/step13.html570
-rw-r--r--o3d/samples/GoogleIO-2009/step14.html581
-rw-r--r--o3d/samples/MANIFEST19
-rw-r--r--o3d/samples/build.scons3
-rw-r--r--o3d/samples/particles.html2
-rw-r--r--o3d/tests/selenium/sample_list.txt2
23 files changed, 4899 insertions, 4 deletions
diff --git a/o3d/DEPS b/o3d/DEPS
index 5e251c1..05d5fb2 100644
--- a/o3d/DEPS
+++ b/o3d/DEPS
@@ -2,7 +2,7 @@ vars = {
"chromium_trunk":
"http://src.chromium.org/svn/trunk",
"nixysa_rev": "25",
- "o3d_code_rev": "89",
+ "o3d_code_rev": "91",
}
deps = {
diff --git a/o3d/DEPS_gyp b/o3d/DEPS_gyp
index 0fbc533..5afa3a2 100644
--- a/o3d/DEPS_gyp
+++ b/o3d/DEPS_gyp
@@ -3,7 +3,7 @@ vars = {
"http://src.chromium.org/svn/trunk",
"nixysa_rev": "25",
"chromium_rev": "19057",
- "o3d_code_rev": "87",
+ "o3d_code_rev": "91",
}
deps = {
diff --git a/o3d/samples/GoogleIO-2009/assets/colorbar.png b/o3d/samples/GoogleIO-2009/assets/colorbar.png
new file mode 100644
index 0000000..629c378
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/assets/colorbar.png
Binary files differ
diff --git a/o3d/samples/GoogleIO-2009/assets/style.css b/o3d/samples/GoogleIO-2009/assets/style.css
new file mode 100644
index 0000000..71fc441
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/assets/style.css
@@ -0,0 +1,8 @@
+html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+}
+
diff --git a/o3d/samples/GoogleIO-2009/shaders/checker.shader b/o3d/samples/GoogleIO-2009/shaders/checker.shader
new file mode 100644
index 0000000..a6c2ae8
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/shaders/checker.shader
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// The 4x4 world view projection matrix.
+float4x4 worldViewProjection : WORLDVIEWPROJECTION;
+float4x4 worldInverseTranspose : WORLDINVERSETRANSPOSE;
+float4x4 world : WORLD;
+
+// light position
+float3 lightWorldPos;
+float3 lightColor;
+
+// input parameters for our vertex shader
+struct VertexShaderInput {
+ float4 position : POSITION;
+ float4 normal : NORMAL;
+ float2 texcoord : TEXCOORD0;
+};
+
+// input parameters for our pixel shader
+struct PixelShaderInput {
+ float4 position : POSITION;
+ float2 texcoord : TEXCOORD0;
+ float3 normal : TEXCOORD1;
+ float3 worldPosition : TEXCOORD2;
+};
+
+// function for getting the checker pattern
+float4 checker(float2 uv) {
+ float checkSize = 10;
+ float fmodResult = fmod(floor(checkSize * uv.x) + floor(checkSize * uv.y),
+ 2.0);
+ return (fmodResult < 1) ?
+ float4(0.4, 0.5, 0.5, 1) :
+ float4(0.6, 0.8, 0.8, 1);
+}
+
+/**
+ * Our vertex shader. In the vertex shader, we calculate the lighting.
+ * Then we'll combine it with our checker pattern input the pixel shader.
+ */
+PixelShaderInput vertexShaderFunction(VertexShaderInput input) {
+ PixelShaderInput output;
+
+ // Transform position into clip space.
+ output.position = mul(input.position, worldViewProjection);
+
+ // Transform normal into world space, where we can do lighting
+ // calculations even if the world transform contains scaling.
+ output.normal = mul(input.normal, worldInverseTranspose).xyz;
+
+ // Calculate surface position in world space.
+ output.worldPosition = mul(input.position, world).xyz;
+
+ output.texcoord = input.texcoord;
+
+ return output;
+}
+
+/**
+ * Our pixel shader. We take the lighting color we got from the vertex sahder
+ * and combine it with our checker pattern. We only need to use the x
+ * coordinate of our input.col because we gave it uniform color
+ */
+float4 pixelShaderFunction(PixelShaderInput input): COLOR {
+ float3 surfaceToLight = normalize(lightWorldPos - input.worldPosition);
+
+ float3 worldNormal = normalize(input.normal);
+
+ // Apply diffuse lighting in world space in case the world transform
+ // contains scaling.
+ float4 check = checker(input.texcoord);
+ float4 directionalIntensity = saturate(dot(worldNormal, surfaceToLight));
+ float4 outColor = directionalIntensity * check;
+ return float4(outColor.rgb, 1);
+}
+
+// Here we tell our effect file *which* functions are
+// our vertex and pixel shaders.
+
+// #o3d VertexShaderEntryPoint vertexShaderFunction
+// #o3d PixelShaderEntryPoint pixelShaderFunction
+// #o3d MatrixLoadOrder RowMajor
diff --git a/o3d/samples/GoogleIO-2009/step01.html b/o3d/samples/GoogleIO-2009/step01.html
new file mode 100644
index 0000000..d105a59
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step01.html
@@ -0,0 +1,176 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateClientSize();
+ updateCamera();
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step02.html b/o3d/samples/GoogleIO-2009/step02.html
new file mode 100644
index 0000000..74f3b0f
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step02.html
@@ -0,0 +1,206 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_playerTransform;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateClientSize();
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ g_playerTransform = g_pack.createObject('Transform');
+ g_playerTransform.parent = g_root;
+ g_playerTransform.addShape(shape);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step03.html b/o3d/samples/GoogleIO-2009/step03.html
new file mode 100644
index 0000000..8f6aaa9
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step03.html
@@ -0,0 +1,254 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<link rel="stylesheet" type="text/css" href="assets/style.css" />
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ g_playerTransform = transform;
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys() {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -3; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 3; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -3; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 3; }
+
+ g_playerXPosition += directionX;
+ g_playerZPosition += directionZ;
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(g_playerXPosition, 0, g_playerZPosition);
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step04.html b/o3d/samples/GoogleIO-2009/step04.html
new file mode 100644
index 0000000..93bd8ed
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step04.html
@@ -0,0 +1,264 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ g_playerTransform = transform;
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ g_playerXPosition += MOVE_VELOCITY * directionX * elapsedTime;
+ g_playerZPosition += MOVE_VELOCITY * directionZ * elapsedTime;
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(g_playerXPosition, 0, g_playerZPosition);
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step05.html b/o3d/samples/GoogleIO-2009/step05.html
new file mode 100644
index 0000000..2c79086
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step05.html
@@ -0,0 +1,292 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ g_playerTransform = transform;
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(g_playerXPosition, 0, g_playerZPosition);
+ }
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step06.html b/o3d/samples/GoogleIO-2009/step06.html
new file mode 100644
index 0000000..131ff43
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step06.html
@@ -0,0 +1,301 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ g_playerTransform = transform;
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(g_playerXPosition, 0, g_playerZPosition);
+ }
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ g_target = [g_playerXPosition, 10, g_playerZPosition];
+ updateCamera();
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step07.html b/o3d/samples/GoogleIO-2009/step07.html
new file mode 100644
index 0000000..4c61f93
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step07.html
@@ -0,0 +1,302 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ g_playerTransform = transform;
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(g_playerXPosition, 0, g_playerZPosition);
+ }
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerXPosition, 10, g_playerZPosition];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step08.html b/o3d/samples/GoogleIO-2009/step08.html
new file mode 100644
index 0000000..dc3084c
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step08.html
@@ -0,0 +1,330 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+var JUMP_VELOCITY = 100;
+var GRAVITY = -500;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerYPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+var g_canJump = true;
+var g_jumping = false;
+var g_playerYVelocity = 0;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ g_playerTransform = transform;
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (g_canJump) {
+ if (g_keyDown[32]) {
+ g_jumping = true;
+ g_canJump = false;
+ g_playerYVelocity = JUMP_VELOCITY;
+ }
+ } else {
+ if (g_jumping) {
+ g_playerYVelocity += GRAVITY * elapsedTime;
+ g_playerYPosition += g_playerYVelocity * elapsedTime;
+ if (g_playerYPosition <= 0) {
+ g_playerYPosition = 0;
+ g_jumping = false;
+ }
+ } else {
+ if (!g_keyDown[32]) {
+ g_canJump = true;
+ }
+ }
+ }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+ }
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(
+ g_playerXPosition, g_playerYPosition, g_playerZPosition);
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerXPosition, 10, g_playerZPosition];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step09.html b/o3d/samples/GoogleIO-2009/step09.html
new file mode 100644
index 0000000..ce931be
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step09.html
@@ -0,0 +1,358 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.particles');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+var JUMP_VELOCITY = 100;
+var GRAVITY = -500;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerYPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+var g_canJump = true;
+var g_jumping = false;
+var g_playerYVelocity = 0;
+var g_particleSystem;
+var g_poofEmitter;
+var g_poof;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var redMaterial = o3djs.material.createBasicMaterial(
+ g_pack,
+ g_viewInfo,
+ [0.2, 1, 0.2, 1]); // green
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Create a cylinder.
+ var shape = o3djs.primitives.createCylinder(
+ g_pack, redMaterial, 2.5, 5, 20, 1,
+ g_math.matrix4.translation([0, 2.5, 0]));
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ g_playerTransform = transform;
+
+ g_particleSystem = o3djs.particles.createParticleSystem(g_pack, g_viewInfo);
+ g_poofEmitter = g_particleSystem.createParticleEmitter();
+ g_poofEmitter.setState(o3djs.particles.ParticleStateIds.ADD);
+ g_poofEmitter.setColorRamp(
+ [1, 1, 1, 0.3,
+ 1, 1, 1, 0]);
+ g_poofEmitter.setParameters({
+ numParticles: 30,
+ lifeTime: 0.5,
+ startTime: 0,
+ startSize: 5,
+ endSize: 10,
+ spinSpeedRange: 10},
+ function(index, parameters) {
+ var angle = Math.random() * 2 * Math.PI;
+ parameters.velocity = g_math.matrix4.transformPoint(
+ g_math.matrix4.rotationY(angle), [25, 2.5, 0]);
+ parameters.acceleration = g_math.mulVectorVector(
+ parameters.velocity, [-1.5, 1, -1.5]);
+ });
+ g_poof = g_poofEmitter.createOneShot(g_root);
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (g_canJump) {
+ if (g_keyDown[32]) {
+ g_jumping = true;
+ g_canJump = false;
+ g_playerYVelocity = JUMP_VELOCITY;
+ }
+ } else {
+ if (g_jumping) {
+ g_playerYVelocity += GRAVITY * elapsedTime;
+ g_playerYPosition += g_playerYVelocity * elapsedTime;
+ if (g_playerYPosition <= 0) {
+ g_playerYPosition = 0;
+ g_poof.trigger(
+ [g_playerXPosition, g_playerYPosition, g_playerZPosition]);
+ g_jumping = false;
+ }
+ } else {
+ if (!g_keyDown[32]) {
+ g_canJump = true;
+ }
+ }
+ }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+ }
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(
+ g_playerXPosition, g_playerYPosition, g_playerZPosition);
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerXPosition, 10, g_playerZPosition];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step10.html b/o3d/samples/GoogleIO-2009/step10.html
new file mode 100644
index 0000000..965ef7c
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step10.html
@@ -0,0 +1,361 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.particles');
+o3djs.require('o3djs.scene');
+o3djs.require('o3djs.pack');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+var JUMP_VELOCITY = 100;
+var GRAVITY = -500;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerYPosition = 0;
+var g_playerZPosition = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+var g_canJump = true;
+var g_jumping = false;
+var g_playerYVelocity = 0;
+var g_particleSystem;
+var g_poofEmitter;
+var g_poof;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Load character.
+ var transform = g_pack.createObject('Transform');
+ g_playerTransform = transform;
+ var playerPack = g_client.createPack();
+ o3djs.scene.loadScene(g_client, playerPack, g_playerTransform,
+ 'assets/character.o3dtgz', initStep3);
+}
+
+/**
+ * Continue setting up after the model has loaded.
+ */
+function initStep3(playerPack, parent, exception) {
+ o3djs.pack.preparePack(playerPack, g_viewInfo);
+ o3djs.material.bindParams(playerPack, g_globalParams);
+ g_playerTransform.parent = g_root;
+
+ g_particleSystem = o3djs.particles.createParticleSystem(g_pack, g_viewInfo);
+ g_poofEmitter = g_particleSystem.createParticleEmitter();
+ g_poofEmitter.setState(o3djs.particles.ParticleStateIds.ADD);
+ g_poofEmitter.setColorRamp(
+ [1, 1, 1, 0.3,
+ 1, 1, 1, 0]);
+ g_poofEmitter.setParameters({
+ numParticles: 30,
+ lifeTime: 0.5,
+ startTime: 0,
+ startSize: 5,
+ endSize: 10,
+ spinSpeedRange: 10},
+ function(index, parameters) {
+ var angle = Math.random() * 2 * Math.PI;
+ parameters.velocity = g_math.matrix4.transformPoint(
+ g_math.matrix4.rotationY(angle), [25, 2.5, 0]);
+ parameters.acceleration = g_math.mulVectorVector(
+ parameters.velocity, [-1.5, 1, -1.5]);
+ });
+ g_poof = g_poofEmitter.createOneShot(g_root);
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (g_canJump) {
+ if (g_keyDown[32]) {
+ g_jumping = true;
+ g_canJump = false;
+ g_playerYVelocity = JUMP_VELOCITY;
+ }
+ } else {
+ if (g_jumping) {
+ g_playerYVelocity += GRAVITY * elapsedTime;
+ g_playerYPosition += g_playerYVelocity * elapsedTime;
+ if (g_playerYPosition <= 0) {
+ g_playerYPosition = 0;
+ g_poof.trigger(
+ [g_playerXPosition, g_playerYPosition, g_playerZPosition]);
+ g_jumping = false;
+ }
+ } else {
+ if (!g_keyDown[32]) {
+ g_canJump = true;
+ }
+ }
+ }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+ }
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(
+ g_playerXPosition, g_playerYPosition, g_playerZPosition);
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerXPosition, 10, g_playerZPosition];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step11.html b/o3d/samples/GoogleIO-2009/step11.html
new file mode 100644
index 0000000..1db5557
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step11.html
@@ -0,0 +1,365 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.particles');
+o3djs.require('o3djs.scene');
+o3djs.require('o3djs.pack');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+var JUMP_VELOCITY = 100;
+var GRAVITY = -500;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerYPosition = 0;
+var g_playerZPosition = 0;
+var g_playerDirection = 0;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+var g_canJump = true;
+var g_jumping = false;
+var g_playerYVelocity = 0;
+var g_particleSystem;
+var g_poofEmitter;
+var g_poof;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Load character.
+ var transform = g_pack.createObject('Transform');
+ g_playerTransform = transform;
+ var playerPack = g_client.createPack();
+ o3djs.scene.loadScene(g_client, playerPack, g_playerTransform,
+ 'assets/character.o3dtgz', initStep3);
+}
+
+/**
+ * Continue setting up after the model has loaded.
+ */
+function initStep3(playerPack, parent, exception) {
+ o3djs.pack.preparePack(playerPack, g_viewInfo);
+ o3djs.material.bindParams(playerPack, g_globalParams);
+ g_playerTransform.parent = g_root;
+
+ g_particleSystem = o3djs.particles.createParticleSystem(g_pack, g_viewInfo);
+ g_poofEmitter = g_particleSystem.createParticleEmitter();
+ g_poofEmitter.setState(o3djs.particles.ParticleStateIds.ADD);
+ g_poofEmitter.setColorRamp(
+ [1, 1, 1, 0.3,
+ 1, 1, 1, 0]);
+ g_poofEmitter.setParameters({
+ numParticles: 30,
+ lifeTime: 0.5,
+ startTime: 0,
+ startSize: 5,
+ endSize: 10,
+ spinSpeedRange: 10},
+ function(index, parameters) {
+ var angle = Math.random() * 2 * Math.PI;
+ parameters.velocity = g_math.matrix4.transformPoint(
+ g_math.matrix4.rotationY(angle), [25, 2.5, 0]);
+ parameters.acceleration = g_math.mulVectorVector(
+ parameters.velocity, [-1.5, 1, -1.5]);
+ });
+ g_poof = g_poofEmitter.createOneShot(g_root);
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (g_canJump) {
+ if (g_keyDown[32]) {
+ g_jumping = true;
+ g_canJump = false;
+ g_playerYVelocity = JUMP_VELOCITY;
+ }
+ } else {
+ if (g_jumping) {
+ g_playerYVelocity += GRAVITY * elapsedTime;
+ g_playerYPosition += g_playerYVelocity * elapsedTime;
+ if (g_playerYPosition <= 0) {
+ g_playerYPosition = 0;
+ g_poof.trigger(
+ [g_playerXPosition, g_playerYPosition, g_playerZPosition]);
+ g_jumping = false;
+ }
+ } else {
+ if (!g_keyDown[32]) {
+ g_canJump = true;
+ }
+ }
+ }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+ var targetDirection = Math.atan2(moveTranslation[0], moveTranslation[2]);
+ g_playerDirection = g_math.lerpRadian(g_playerDirection, targetDirection,
+ 0.2);
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+ }
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(
+ g_playerXPosition, g_playerYPosition, g_playerZPosition);
+ g_playerTransform.rotateY(g_playerDirection);
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerXPosition, 10, g_playerZPosition];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step12.html b/o3d/samples/GoogleIO-2009/step12.html
new file mode 100644
index 0000000..cb07ce7
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step12.html
@@ -0,0 +1,394 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.particles');
+o3djs.require('o3djs.scene');
+o3djs.require('o3djs.pack');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+var JUMP_VELOCITY = 100;
+var GRAVITY = -500;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerXPosition = 0;
+var g_playerYPosition = 0;
+var g_playerZPosition = 0;
+var g_playerDirection = 0;
+var g_animParam;
+var g_playerMode;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+var g_canJump = true;
+var g_jumping = false;
+var g_playerYVelocity = 0;
+var g_particleSystem;
+var g_poofEmitter;
+var g_poof;
+
+var IDLE_START_TIME = 247 / 30;
+var IDLE_END_TIME = 573 / 30;
+var IDLE_TIME_RANGE = IDLE_END_TIME - IDLE_START_TIME;
+
+var g_animTimer = IDLE_START_TIME;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Load character.
+ var transform = g_pack.createObject('Transform');
+ g_playerTransform = transform;
+ var playerPack = g_client.createPack();
+ var paramObject = playerPack.createObject('ParamObject');
+ g_animParam = paramObject.createParam('animTime', 'ParamFloat');
+ o3djs.scene.loadScene(g_client, playerPack, g_playerTransform,
+ 'assets/character.o3dtgz', initStep3,
+ {opt_animSource: g_animParam});
+}
+
+/**
+ * Continue setting up after the model has loaded.
+ */
+function initStep3(playerPack, parent, exception) {
+ o3djs.pack.preparePack(playerPack, g_viewInfo);
+ o3djs.material.bindParams(playerPack, g_globalParams);
+ g_playerTransform.parent = g_root;
+
+ g_particleSystem = o3djs.particles.createParticleSystem(g_pack, g_viewInfo);
+ g_poofEmitter = g_particleSystem.createParticleEmitter();
+ g_poofEmitter.setState(o3djs.particles.ParticleStateIds.ADD);
+ g_poofEmitter.setColorRamp(
+ [1, 1, 1, 0.3,
+ 1, 1, 1, 0]);
+ g_poofEmitter.setParameters({
+ numParticles: 30,
+ lifeTime: 0.5,
+ startTime: 0,
+ startSize: 5,
+ endSize: 10,
+ spinSpeedRange: 10},
+ function(index, parameters) {
+ var angle = Math.random() * 2 * Math.PI;
+ parameters.velocity = g_math.matrix4.transformPoint(
+ g_math.matrix4.rotationY(angle), [25, 2.5, 0]);
+ parameters.acceleration = g_math.mulVectorVector(
+ parameters.velocity, [-1.5, 1, -1.5]);
+ });
+ g_poof = g_poofEmitter.createOneShot(g_root);
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+ window.o3d_prepForSelenium = function() {
+ g_animParam.value = 0;
+ g_animParam = {value: 0};
+ }
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (g_canJump) {
+ if (g_keyDown[32]) {
+ g_jumping = true;
+ g_canJump = false;
+ g_playerYVelocity = JUMP_VELOCITY;
+ }
+ } else {
+ if (g_jumping) {
+ g_playerYVelocity += GRAVITY * elapsedTime;
+ g_playerYPosition += g_playerYVelocity * elapsedTime;
+ if (g_playerYPosition <= 0) {
+ g_playerYPosition = 0;
+ g_poof.trigger(
+ [g_playerXPosition, g_playerYPosition, g_playerZPosition]);
+ g_jumping = false;
+ }
+ } else {
+ if (!g_keyDown[32]) {
+ g_canJump = true;
+ }
+ }
+ }
+
+ if (directionX != 0 || directionZ != 0) {
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX * elapsedTime,
+ 0,
+ MOVE_VELOCITY * directionZ * elapsedTime]);
+ var targetDirection = Math.atan2(moveTranslation[0], moveTranslation[2]);
+ g_playerDirection = g_math.lerpRadian(g_playerDirection, targetDirection,
+ 0.2);
+ g_playerXPosition += moveTranslation[0];
+ g_playerZPosition += moveTranslation[2];
+ }
+
+ g_playerTransform.identity();
+ g_playerTransform.translate(
+ g_playerXPosition, g_playerYPosition, g_playerZPosition);
+ g_playerTransform.rotateY(g_playerDirection);
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerXPosition, 10, g_playerZPosition];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Deal with player animation.
+ */
+function handleAnimation(elapsedTime) {
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= IDLE_END_TIME) {
+ g_animTimer = g_math.modClamp(g_animTimer,
+ IDLE_TIME_RANGE,
+ IDLE_START_TIME);
+ }
+ g_animParam.value = g_animTimer;
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ handleAnimation(elapsedTime);
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step13.html b/o3d/samples/GoogleIO-2009/step13.html
new file mode 100644
index 0000000..a995627
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step13.html
@@ -0,0 +1,570 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.particles');
+o3djs.require('o3djs.scene');
+o3djs.require('o3djs.pack');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+var JUMP_VELOCITY = 100;
+var GRAVITY = -500;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerPosition = [0, 0, 0];
+var g_playerDirection = 0;
+var g_animParam;
+var g_playerMode;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+var g_canJump = true;
+var g_jumping = false;
+var g_playerVelocity = [0, 0, 0];
+var g_targetDirection = 0;
+var g_particleSystem;
+var g_poofEmitter;
+var g_poof;
+
+var g_anims = {
+ idle1: {startFrame: 0, endFrame: 30},
+ walk: {startFrame: 31, endFrame: 71},
+ jumpStart: {startFrame: 72, endFrame: 87},
+ jumpUp: {startFrame: 87, endFrame: 87},
+ jumpCrest: {startFrame: 87, endFrame: 91},
+ jumpFall: {startFrame: 91, endFrame: 91},
+ jumpLand: {startFrame: 91, endFrame: 110},
+ run: {startFrame: 111, endFrame: 127},
+ idle2: {startFrame: 128, endFrame: 173},
+ idle3: {startFrame: 174, endFrame: 246},
+ idle4: {startFrame: 247, endFrame: 573}};
+
+var g_animation;
+var g_animTimer;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 5000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Start an animation.
+ * @param {!Object} animation to start.
+ */
+function startAnimation(animation) {
+ g_animation = animation;
+ g_animTimer = g_animation.startTime;
+}
+
+/**
+ * Starts a new mode.
+ * @param {number} mode Mode to start.
+ */
+function startMode(mode) {
+ if (mode != g_playerMode) {
+ g_playerMode = mode;
+ mode.init();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Convert anim frames to anim times.
+ for (var animName in g_anims) {
+ var anim = g_anims[animName];
+ anim.startTime = anim.startFrame / 30;
+ anim.endTime = anim.endFrame / 30;
+ anim.timeRange = anim.endTime - anim.startTime;
+ }
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ var checkerMaterial = o3djs.material.createMaterialFromFile(
+ g_pack, 'shaders/checker.shader', g_viewInfo.performanceDrawList);
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [30, 60, 40];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Create a ground plane.
+ var shape = o3djs.primitives.createPlane(
+ g_pack, checkerMaterial, 100, 100, 10, 10);
+ var transform = g_pack.createObject('Transform');
+ transform.parent = g_root;
+ transform.addShape(shape);
+
+ // Load character.
+ var transform = g_pack.createObject('Transform');
+ g_playerTransform = transform;
+ var playerPack = g_client.createPack();
+ var paramObject = playerPack.createObject('ParamObject');
+ g_animParam = paramObject.createParam('animTime', 'ParamFloat');
+ o3djs.scene.loadScene(g_client, playerPack, g_playerTransform,
+ 'assets/character.o3dtgz', initStep3,
+ {opt_animSource: g_animParam});
+}
+
+/**
+ * Continue setting up after the model has loaded.
+ */
+function initStep3(playerPack, parent, exception) {
+ o3djs.pack.preparePack(playerPack, g_viewInfo);
+ o3djs.material.bindParams(playerPack, g_globalParams);
+ g_playerTransform.parent = g_root;
+
+ g_particleSystem = o3djs.particles.createParticleSystem(g_pack, g_viewInfo);
+ g_poofEmitter = g_particleSystem.createParticleEmitter();
+ g_poofEmitter.setState(o3djs.particles.ParticleStateIds.ADD);
+ g_poofEmitter.setColorRamp(
+ [1, 1, 1, 0.3,
+ 1, 1, 1, 0]);
+ g_poofEmitter.setParameters({
+ numParticles: 30,
+ lifeTime: 0.5,
+ startTime: 0,
+ startSize: 5,
+ endSize: 10,
+ spinSpeedRange: 10},
+ function(index, parameters) {
+ var angle = Math.random() * 2 * Math.PI;
+ parameters.velocity = g_math.matrix4.transformPoint(
+ g_math.matrix4.rotationY(angle), [25, 2.5, 0]);
+ parameters.acceleration = g_math.mulVectorVector(
+ parameters.velocity, [-1.5, 1, -1.5]);
+ });
+ g_poof = g_poofEmitter.createOneShot(g_root);
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+ window.o3d_prepForSelenium = function() {
+ g_animParam.value = 0;
+ g_animParam = {value: 0};
+ }
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (g_canJump) {
+ if (g_keyDown[32]) {
+ startMode(g_modes.JUMP);
+ }
+ } else {
+ if (!g_jumping) {
+ if (!g_keyDown[32]) {
+ g_canJump = true;
+ }
+ }
+ }
+
+ if (directionX != 0 || directionZ != 0) {
+ if (!g_jumping) {
+ startMode(g_modes.WALK);
+ }
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX, 0, MOVE_VELOCITY * directionZ]);
+ g_targetDirection = Math.atan2(moveTranslation[0],
+ moveTranslation[2]);
+ g_playerVelocity[0] = moveTranslation[0];
+ g_playerVelocity[2] = moveTranslation[2];
+ } else {
+ g_playerVelocity[0] = 0;
+ g_playerVelocity[2] = 0;
+ if (!g_jumping) {
+ startMode(g_modes.IDLE);
+ }
+ }
+}
+
+/**
+ * Moves the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerPosition[0], 10, g_playerPosition[2]];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Updates the direction.
+ * @param {number} elapsedTime Time elasped since last frame.
+ */
+function updateDirection(elapsedTime) {
+ g_playerDirection = g_math.lerpRadian(g_playerDirection, g_targetDirection,
+ 0.2);
+}
+
+/**
+ * Adds gravity to velocity.
+ * @param {number} elapsedTime Time elasped since last frame.
+ */
+function calculateGravity(elapsedTime) {
+ g_playerVelocity[1] += GRAVITY * elapsedTime;
+}
+
+/**
+ * Updates the player's position.
+ * @param {number} elapsedTime Time elasped since last frame.
+ */
+function updateMovement(elapsedTime) {
+ g_playerPosition = g_math.addVector(g_playerPosition,
+ g_math.mulVectorScalar(g_playerVelocity,
+ elapsedTime));
+}
+
+var g_modes = {};
+
+/**
+ * Handle idle mode.
+ */
+g_modes.IDLE = {
+ init: function() {
+ startAnimation(g_anims.idle1);
+ g_jumping = false;
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ // Pick an idle at random.
+ var idle = 0;
+ if (Math.random() > 0.8) {
+ // Choose another idle.
+ idle = Math.floor(Math.random() * 10 / 3);
+ if (idle > 3) {
+ idle = 3;
+ }
+ }
+ var idleName = 'idle' + (idle + 1);
+ startAnimation(g_anims[idleName]);
+ }
+ }
+};
+
+/**
+ * Handle walk mode.
+ */
+g_modes.WALK = {
+ init: function() {
+ startAnimation(g_anims.run);
+ g_jumping = false;
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ updateMovement(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ g_animTimer = g_math.modClamp(g_animTimer,
+ g_animation.timeRange,
+ g_animation.startTime);
+ }
+ }
+};
+
+/**
+ * Handle jump mode.
+ */
+g_modes.JUMP = {
+ init: function() {
+ startAnimation(g_anims.jumpStart);
+ g_jumping = true;
+ g_canJump = false;
+ g_playerVelocity[1] = JUMP_VELOCITY;
+ },
+ handle: function(elapsedTime) {
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ startMode(g_modes.JUMP_UP);
+ }
+ }
+};
+
+g_modes.JUMP_UP = {
+ init: function() {
+ startAnimation(g_anims.jumpUp);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ calculateGravity(elapsedTime);
+ updateMovement(elapsedTime);
+ if (g_playerVelocity[1] < 10) {
+ startMode(g_modes.JUMP_CREST);
+ }
+ }
+};
+
+g_modes.JUMP_CREST = {
+ init: function() {
+ startAnimation(g_anims.jumpCrest);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ calculateGravity(elapsedTime);
+ updateMovement(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ startMode(g_modes.JUMP_FALL);
+ }
+ }
+};
+
+g_modes.JUMP_FALL = {
+ init: function() {
+ startAnimation(g_anims.jumpFall);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ calculateGravity(elapsedTime);
+ updateMovement(elapsedTime);
+ if (g_playerPosition[1] <= 0) {
+ startMode(g_modes.JUMP_LAND);
+ g_playerPosition[1] = 0;
+ g_playerVelocity[1] = 0;
+ g_poof.trigger(g_playerPosition);
+ }
+ }
+};
+
+g_modes.JUMP_LAND = {
+ init: function() {
+ startAnimation(g_anims.jumpLand);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ g_jumping = false;
+ startMode(g_modes.IDLE);
+ }
+ }
+};
+
+function updatePlayer() {
+ g_animParam.value = g_animTimer;
+ g_playerTransform.identity();
+ g_playerTransform.translate(g_playerPosition);
+ g_playerTransform.rotateY(g_playerDirection);
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ g_playerMode.handle(elapsedTime);
+ updatePlayer();
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/GoogleIO-2009/step14.html b/o3d/samples/GoogleIO-2009/step14.html
new file mode 100644
index 0000000..031f858
--- /dev/null
+++ b/o3d/samples/GoogleIO-2009/step14.html
@@ -0,0 +1,581 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!--
+Google I/O O3D Sample.
+
+This sample shows the steps to make a simple frame rate independent game.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Google I/O O3D Sample
+</title>
+<style type="text/css">
+ html, body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ font-family: Arial, sans-serif;
+ }
+</style>
+<!-- Include sample javascript library functions-->
+<script type="text/javascript" src="../o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.particles');
+o3djs.require('o3djs.scene');
+o3djs.require('o3djs.pack');
+o3djs.require('o3djs.loader');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload= unload;
+
+// constants
+var MOVE_VELOCITY = 25; // in units per second.
+var JUMP_VELOCITY = 100;
+var GRAVITY = -500;
+
+// global variables
+var g_o3dElement;
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_pack;
+var g_root;
+var g_globalParams;
+var g_o3dWidth;
+var g_o3dHeight;
+var g_o3dElement;
+var g_keyDown = []; // which keys are down by key code.
+var g_playerTransform;
+var g_playerPosition = [0, 0, 0];
+var g_playerDirection = 0;
+var g_animParam;
+var g_playerMode;
+var g_eye = [15, 25, 50];
+var g_target = [0, 10, 0];
+var g_up = [0, 1, 0];
+var g_viewMatrix;
+var g_moveMatrix;
+var g_canJump = true;
+var g_jumping = false;
+var g_playerVelocity = [0, 0, 0];
+var g_targetDirection = 0;
+var g_worldTransform;
+var g_particleSystem;
+var g_poofEmitter;
+var g_poof;
+
+var g_anims = {
+ idle1: {startFrame: 0, endFrame: 30},
+ walk: {startFrame: 31, endFrame: 71},
+ jumpStart: {startFrame: 72, endFrame: 87},
+ jumpUp: {startFrame: 87, endFrame: 87},
+ jumpCrest: {startFrame: 87, endFrame: 91},
+ jumpFall: {startFrame: 91, endFrame: 91},
+ jumpLand: {startFrame: 91, endFrame: 110},
+ run: {startFrame: 111, endFrame: 127},
+ idle2: {startFrame: 128, endFrame: 173},
+ idle3: {startFrame: 174, endFrame: 246},
+ idle4: {startFrame: 247, endFrame: 573}};
+
+var g_animation;
+var g_animTimer;
+
+/**
+ * Updates the projection matrix.
+ */
+function updateProjection() {
+ g_viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // field of view.
+ g_o3dWidth / g_o3dHeight, // aspect ratio
+ 0.1, // Near plane.
+ 15000); // Far plane.
+}
+
+/**
+ * Given a view matrix computes an movement matrix to make it easy
+ * to move something relative to the camera view in the XZ plane.
+ * @param {!o3djs.math.Matrix4} viewMatrix A view matrix.
+ * @return {!o3djs.math.Matrix4} A movement matrix.
+ */
+function computeMoveMatrixFromViewMatrix(viewMatrix) {
+ var cameraMatrix = g_math.matrix4.inverse(viewMatrix);
+ var xAxis = g_math.cross([0, 1, 0], cameraMatrix[2].slice(0, 3));
+ var zAxis = g_math.cross(xAxis, [0, 1, 0]);
+ return [
+ xAxis.concat(0),
+ [0, 1, 0, 0],
+ zAxis.concat(0),
+ [0, 0, 0, 1]];
+}
+
+/*
+ * Updates the camera.
+ */
+function updateCamera() {
+ g_viewMatrix = g_math.matrix4.lookAt(g_eye, g_target, g_up);
+ g_viewInfo.drawContext.view = g_viewMatrix;
+ g_moveMatrix = computeMoveMatrixFromViewMatrix(g_viewMatrix);
+};
+
+/**
+ * Updates global variables of the client's size if they have changed.
+ */
+function updateClientSize() {
+ var newWidth = g_client.width;
+ var newHeight = g_client.height;
+ if (g_o3dWidth != newWidth || g_o3dHeight != newHeight) {
+ g_o3dWidth = newWidth;
+ g_o3dHeight = newHeight;
+ updateProjection();
+ }
+}
+
+/**
+ * Start an animation.
+ * @param {!Object} animation to start.
+ */
+function startAnimation(animation) {
+ g_animation = animation;
+ g_animTimer = g_animation.startTime;
+}
+
+/**
+ * Starts a new mode.
+ * @param {number} mode Mode to start.
+ */
+function startMode(mode) {
+ if (mode != g_playerMode) {
+ g_playerMode = mode;
+ mode.init();
+ }
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and creates one shape.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ g_o3dElement = clientElements[0];
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = g_o3dElement.client;
+
+ // Convert anim frames to anim times.
+ for (var animName in g_anims) {
+ var anim = g_anims[animName];
+ anim.startTime = anim.startFrame / 30;
+ anim.endTime = anim.endFrame / 30;
+ anim.timeRange = anim.endTime - anim.startTime;
+ }
+
+ // Creates a pack to manage our resources/assets
+ g_pack = g_client.createPack();
+
+ g_root = g_pack.createObject('Transform');
+
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_root,
+ g_client.renderGraphRoot);
+
+ updateCamera();
+
+ g_globalParams = o3djs.material.createAndBindStandardParams(g_pack);
+ g_globalParams.lightWorldPos.value = [600, 2000, 400];
+ g_globalParams.lightColor.value = [1, 1, 1, 1];
+
+ // Load character.
+ var transform = g_pack.createObject('Transform');
+ g_playerTransform = transform;
+ var playerPack = g_client.createPack();
+ var paramObject = playerPack.createObject('ParamObject');
+ g_animParam = paramObject.createParam('animTime', 'ParamFloat');
+ var loader = o3djs.loader.createLoader(initStep3);
+ loader.loadScene(g_client, playerPack, g_playerTransform,
+ 'assets/character.o3dtgz', prepareScene,
+ {opt_animSource: g_animParam});
+ var worldPack = g_client.createPack();
+ g_worldTransform = worldPack.createObject('Transform');
+ loader.loadScene(g_client, worldPack, g_worldTransform,
+ 'assets/background.o3dtgz', prepareScene)
+ loader.finish();
+}
+
+/**
+ * Setup the just loaded scene.
+ * @param {!o3d.Pack} pack The pack the scene was loaded into.
+ * @param {!o3d.Transform} parent The parent of the scene.
+ * @param {*} exception An exception or null if success.
+ */
+function prepareScene(pack, parent, exception) {
+ o3djs.pack.preparePack(pack, g_viewInfo);
+ o3djs.material.bindParams(pack, g_globalParams);
+ parent.parent = g_root;
+}
+
+/**
+ * Continue setting up after the both the model and character have loaded.
+ */
+function initStep3() {
+ // Fix for artists not using the same scale on background vs character
+ g_worldTransform.scale(10, 10, 10);
+ // Fix for current collada import bugs.
+ var m = g_client.getObjects('Road', 'o3d.Material')[0];
+ m.getParam('shininess').value = 100;
+
+ g_particleSystem = o3djs.particles.createParticleSystem(g_pack, g_viewInfo);
+ g_poofEmitter = g_particleSystem.createParticleEmitter();
+ g_poofEmitter.setState(o3djs.particles.ParticleStateIds.ADD);
+ g_poofEmitter.setColorRamp(
+ [1, 1, 1, 0.3,
+ 1, 1, 1, 0]);
+ g_poofEmitter.setParameters({
+ numParticles: 30,
+ lifeTime: 0.5,
+ startTime: 0,
+ startSize: 5,
+ endSize: 10,
+ spinSpeedRange: 10},
+ function(index, parameters) {
+ var angle = Math.random() * 2 * Math.PI;
+ parameters.velocity = g_math.matrix4.transformPoint(
+ g_math.matrix4.rotationY(angle), [25, 2.5, 0]);
+ parameters.acceleration = g_math.mulVectorVector(
+ parameters.velocity, [-1.5, 1, -1.5]);
+ });
+ g_poof = g_poofEmitter.createOneShot(g_root);
+
+ // Setup a render callback for per frame processing.
+ g_client.setRenderCallback(onRender);
+
+ o3djs.event.addEventListener(g_o3dElement, 'keydown', onKeyDown);
+ o3djs.event.addEventListener(g_o3dElement, 'keyup', onKeyUp);
+
+ window.g_finished = true; // for selenium testing.
+ window.o3d_prepForSelenium = function() {
+ g_animParam.value = 0;
+ g_animParam = {value: 0};
+ }
+}
+
+/**
+ * Tracks key down events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyDown(e) {
+ g_keyDown[e.keyCode] = true;
+}
+
+/**
+ * Tracks key up events.
+ * @param {Event} e keyboard event.
+ */
+function onKeyUp(e) {
+ g_keyDown[e.keyCode] = false;
+}
+
+/**
+ * Look at keys.
+ */
+function handleMoveKeys(elapsedTime) {
+ var directionX = 0;
+ var directionZ = 0;
+
+ if (g_keyDown[37] || g_keyDown[65]) { directionX = -1; }
+ if (g_keyDown[39] || g_keyDown[68]) { directionX = 1; }
+ if (g_keyDown[38] || g_keyDown[87]) { directionZ = -1; }
+ if (g_keyDown[40] || g_keyDown[83]) { directionZ = 1; }
+
+ if (g_canJump) {
+ if (g_keyDown[32]) {
+ startMode(g_modes.JUMP);
+ }
+ } else {
+ if (!g_jumping) {
+ if (!g_keyDown[32]) {
+ g_canJump = true;
+ }
+ }
+ }
+
+ if (directionX != 0 || directionZ != 0) {
+ if (!g_jumping) {
+ startMode(g_modes.WALK);
+ }
+ var moveTranslation = g_math.matrix4.transformPoint(
+ g_moveMatrix,
+ [MOVE_VELOCITY * directionX, 0, MOVE_VELOCITY * directionZ]);
+ g_targetDirection = Math.atan2(moveTranslation[0],
+ moveTranslation[2]);
+ g_playerVelocity[0] = moveTranslation[0];
+ g_playerVelocity[2] = moveTranslation[2];
+ } else {
+ g_playerVelocity[0] = 0;
+ g_playerVelocity[2] = 0;
+ if (!g_jumping) {
+ startMode(g_modes.IDLE);
+ }
+ }
+}
+
+/**
+ * Move the camera.
+ */
+function moveCamera() {
+ var newTarget = [g_playerPosition[0], 10, g_playerPosition[2]];
+ g_target = g_math.lerpVector(g_target, newTarget, 0.03);
+ updateCamera();
+}
+
+/**
+ * Updates the direction.
+ * @param {number} elapsedTime Time elasped since last frame.
+ */
+function updateDirection(elapsedTime) {
+ g_playerDirection = g_math.lerpRadian(g_playerDirection, g_targetDirection,
+ 0.2);
+}
+
+/**
+ * Adds gravity to velocity.
+ * @param {number} elapsedTime Time elasped since last frame.
+ */
+function calculateGravity(elapsedTime) {
+ g_playerVelocity[1] += GRAVITY * elapsedTime;
+}
+
+/**
+ * Updates the player's position.
+ * @param {number} elapsedTime Time elasped since last frame.
+ */
+function updateMovement(elapsedTime) {
+ g_playerPosition = g_math.addVector(g_playerPosition,
+ g_math.mulVectorScalar(g_playerVelocity,
+ elapsedTime));
+}
+
+var g_modes = {};
+
+/**
+ * Handle idle mode.
+ */
+g_modes.IDLE = {
+ init: function() {
+ startAnimation(g_anims.idle1);
+ g_jumping = false;
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ // Pick an idle at random.
+ var idle = 0;
+ if (Math.random() > 0.8) {
+ // Choose another idle.
+ idle = Math.floor(Math.random() * 10 / 3);
+ if (idle > 3) {
+ idle = 3;
+ }
+ }
+ var idleName = 'idle' + (idle + 1);
+ startAnimation(g_anims[idleName]);
+ }
+ }
+};
+
+/**
+ * Handle walk mode.
+ */
+g_modes.WALK = {
+ init: function() {
+ startAnimation(g_anims.run);
+ g_jumping = false;
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ updateMovement(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ g_animTimer = g_math.modClamp(g_animTimer,
+ g_animation.timeRange,
+ g_animation.startTime);
+ }
+ }
+};
+
+/**
+ * Handle jump mode.
+ */
+g_modes.JUMP = {
+ init: function() {
+ startAnimation(g_anims.jumpStart);
+ g_jumping = true;
+ g_canJump = false;
+ g_playerVelocity[1] = JUMP_VELOCITY;
+ },
+ handle: function(elapsedTime) {
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ startMode(g_modes.JUMP_UP);
+ }
+ }
+};
+
+g_modes.JUMP_UP = {
+ init: function() {
+ startAnimation(g_anims.jumpUp);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ calculateGravity(elapsedTime);
+ updateMovement(elapsedTime);
+ if (g_playerVelocity[1] < 10) {
+ startMode(g_modes.JUMP_CREST);
+ }
+ }
+};
+
+g_modes.JUMP_CREST = {
+ init: function() {
+ startAnimation(g_anims.jumpCrest);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ calculateGravity(elapsedTime);
+ updateMovement(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ startMode(g_modes.JUMP_FALL);
+ }
+ }
+};
+
+g_modes.JUMP_FALL = {
+ init: function() {
+ startAnimation(g_anims.jumpFall);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ calculateGravity(elapsedTime);
+ updateMovement(elapsedTime);
+ if (g_playerPosition[1] <= 0) {
+ startMode(g_modes.JUMP_LAND);
+ g_playerPosition[1] = 0;
+ g_playerVelocity[1] = 0;
+ g_poof.trigger(g_playerPosition);
+ }
+ }
+};
+
+g_modes.JUMP_LAND = {
+ init: function() {
+ startAnimation(g_anims.jumpLand);
+ },
+ handle: function(elapsedTime) {
+ updateDirection(elapsedTime);
+ g_animTimer += elapsedTime;
+ if (g_animTimer >= g_animation.endTime) {
+ g_jumping = false;
+ startMode(g_modes.IDLE);
+ }
+ }
+};
+
+function updatePlayer() {
+ g_animParam.value = g_animTimer;
+ g_playerTransform.identity();
+ g_playerTransform.translate(g_playerPosition);
+ g_playerTransform.rotateY(g_playerDirection);
+}
+
+/**
+ * Called every frame.
+ * @param {!o3d.RenderEvent} renderEvent Rendering Information.
+ */
+function onRender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+ updateClientSize();
+ handleMoveKeys(elapsedTime);
+ g_playerMode.handle(elapsedTime);
+ updatePlayer();
+ moveCamera();
+};
+
+/**
+ * Remove any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<table style="width: 100%; height:100%;">
+ <tr style="height: 50px;"><td>
+ <div style="width: 100%; height: 50px; font-size: large;">
+ <img src="assets/colorbar.png" width="100%" height="10px"/><br/>
+ Google I/O 2009 O3D Sample
+ </div>
+ </td></tr>
+ <tr style="height: 100%;"><td>
+ <div style="width: 100%; height: 100%;">
+ <div id="o3d" style="width: 100%; height: 100%;"></div>
+ </div>
+ </td></tr>
+</table>
+</body>
+</html>
diff --git a/o3d/samples/MANIFEST b/o3d/samples/MANIFEST
index f7f7d63..5cb2ff6 100644
--- a/o3d/samples/MANIFEST
+++ b/o3d/samples/MANIFEST
@@ -44,6 +44,25 @@ beachdemo/assets/pe_mist.png
beachdemo/assets/sky-cubemap.dds
beachdemo/beachdemo.html
beachdemo/beachdemo.js
+GoogleIO-2009/step01.html
+GoogleIO-2009/step02.html
+GoogleIO-2009/step03.html
+GoogleIO-2009/step04.html
+GoogleIO-2009/step05.html
+GoogleIO-2009/step06.html
+GoogleIO-2009/step07.html
+GoogleIO-2009/step08.html
+GoogleIO-2009/step09.html
+GoogleIO-2009/step10.html
+GoogleIO-2009/step11.html
+GoogleIO-2009/step12.html
+GoogleIO-2009/step13.html
+GoogleIO-2009/step14.html
+GoogleIO-2009/shaders/checker.shader
+GoogleIO-2009/assets/background.o3dtgz
+GoogleIO-2009/assets/character.o3dtgz
+GoogleIO-2009/assets/colorbar.png
+GoogleIO-2009/assets/style.css
box2d-3d/box2d-3d.html
box2d-3d/demos/LICENSE.txt
box2d-3d/demos/README.o3d
diff --git a/o3d/samples/build.scons b/o3d/samples/build.scons
index c1324ba..608b2ad 100644
--- a/o3d/samples/build.scons
+++ b/o3d/samples/build.scons
@@ -254,7 +254,8 @@ z_up_env = env.Clone(UP_AXIS='0,0,1')
models = [
{'path': 'beachdemo/convert_assets/beachdemo.zip', 'env': z_up_env},
{'path': 'beachdemo/convert_assets/beach-low-poly.dae', 'env': z_up_env},
-
+ {'path': 'GoogleIO-2009/convert_assets/background.zip', 'env': y_up_env},
+ {'path': 'GoogleIO-2009/convert_assets/character.zip', 'env': y_up_env},
{'path': 'home-configurators/convert_cbassets/House_Roofless.kmz',
'env': z_up_env},
diff --git a/o3d/samples/particles.html b/o3d/samples/particles.html
index a82b334..244b621 100644
--- a/o3d/samples/particles.html
+++ b/o3d/samples/particles.html
@@ -594,6 +594,6 @@ function unload() {
<div id="o3d" style="width: 800px; height: 600px;"></div>
<!-- End of O3D plugin -->
Press 'P' to make a poof.<br/>
-Press 'T' to make a trail.
+Hold 'T' to make a trail.
</body>
</html>
diff --git a/o3d/tests/selenium/sample_list.txt b/o3d/tests/selenium/sample_list.txt
index 786bbc4..2774574 100644
--- a/o3d/tests/selenium/sample_list.txt
+++ b/o3d/tests/selenium/sample_list.txt
@@ -107,6 +107,8 @@ medium zsorting screenshot pdiff_threshold(39500)
#large box2d-3d/box2d-3d timeout(45000) except(*googlechrome)
large simpleviewer/simpleviewer screenshot pdiff_threshold(100)
large trends/trends timeout(30000)
+medium GoogleIO-2009/step09 screenshot pdiff_threshold(1900)
+large GoogleIO-2009/step14 screenshot pdiff_threshold(4900)
# -- tests below this line are tests for which there is a python
# function to custom run the test. As such, only the 'except' and