diff options
Diffstat (limited to 'o3d/samples/GoogleIO-2009/step13.html')
-rw-r--r-- | o3d/samples/GoogleIO-2009/step13.html | 570 |
1 files changed, 570 insertions, 0 deletions
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> |