rename ObsoleteDemos back to Demos

fix some relative path issues for loading assets
This commit is contained in:
Erwin Coumans
2014-05-12 16:12:01 -07:00
parent 23a2a4f4f9
commit dc491936a2
312 changed files with 3933 additions and 322 deletions

View File

@@ -0,0 +1,22 @@
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview This class implements an extension to Function object that
* lets you bind a scope for |this| to a function.
*/
/**
* Bind a scope to a function. Used to bind an object to |this| for event
* handlers.
* @param {!Object} scope The scope in which the function executes. |scope|
* becomes |this| during function execution.
* @return {function} the bound version of the original function.
*/
Function.prototype.bind = function(scope) {
var boundContext = this;
return function() {
return boundContext.apply(scope, arguments);
}
}

View File

@@ -0,0 +1,134 @@
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview This class implements a mouse-drag event. It registers for
* mousedown events, and when it sees one, starts capturing mousemove events
* until it gets a mousup event. It manufactures three drag events: the
* DRAG_START, DRAG and DRAG_END.
*/
// Requires bind
/**
* Constructor for the Dragger. Register for mousedown events that happen on
* |opt_target|. If |opt_target| is null or undefined, then this object
* observes mousedown on the whole document.
* @param {?Element} opt_target The event target. Defaults to the whole
* document.
* @constructor
*/
tumbler.Dragger = function(opt_target) {
/**
* The event target.
* @type {Element}
* @private
*/
this.target_ = opt_target || document;
/**
* The array of objects that get notified of drag events. Each object in
* this array get sent a handleStartDrag(), handleDrag() and handleEndDrag()
* message.
* @type {Array.<Object>}
* @private
*/
this.listeners_ = [];
/**
* Flag to indicate whether the object is in a drag sequence or not.
* @type {boolean}
* @private
*/
this.isDragging_ = false;
/**
* The function objects that get attached as event handlers. These are
* cached so that they can be removed on mouse up.
* @type {function}
* @private
*/
this.boundMouseMove_ = null;
this.boundMouseUp_ = null;
this.target_.addEventListener('mousedown',
this.onMouseDown.bind(this),
false);
}
/**
* The ids used for drag event types.
* @enum {string}
*/
tumbler.Dragger.DragEvents = {
DRAG_START: 'dragstart', // Start a drag sequence
DRAG: 'drag', // Mouse moved during a drag sequence.
DRAG_END: 'dragend' // End a drag sewquence.
};
/**
* Add a drag listener. Each listener should respond to thhree methods:
* handleStartDrag(), handleDrag() and handleEndDrag(). This method assumes
* that |listener| does not already exist in the array of listeners.
* @param {!Object} listener The object that will listen to drag events.
*/
tumbler.Dragger.prototype.addDragListener = function(listener) {
this.listeners_.push(listener);
}
/**
* Handle a mousedown event: register for mousemove and mouseup, then tell
* the target that is has a DRAG_START event.
* @param {Event} event The mousedown event that triggered this method.
*/
tumbler.Dragger.prototype.onMouseDown = function(event) {
this.boundMouseMove_ = this.onMouseMove.bind(this);
this.boundMouseUp_ = this.onMouseUp.bind(this);
this.target_.addEventListener('mousemove', this.boundMouseMove_);
this.target_.addEventListener('mouseup', this.boundMouseUp_);
this.isDragging_ = true;
var dragStartEvent = { type: tumbler.Dragger.DragEvents.DRAG_START,
clientX: event.offsetX,
clientY: event.offsetY };
var i;
for (i = 0; i < this.listeners_.length; ++i) {
this.listeners_[i].handleStartDrag(this.target_, dragStartEvent);
}
}
/**
* Handle a mousemove event: tell the target that is has a DRAG event.
* @param {Event} event The mousemove event that triggered this method.
*/
tumbler.Dragger.prototype.onMouseMove = function(event) {
if (!this.isDragging_)
return;
var dragEvent = { type: tumbler.Dragger.DragEvents.DRAG,
clientX: event.offsetX,
clientY: event.offsetY};
var i;
for (i = 0; i < this.listeners_.length; ++i) {
this.listeners_[i].handleDrag(this.target_, dragEvent);
}
}
/**
* Handle a mouseup event: un-register for mousemove and mouseup, then tell
* the target that is has a DRAG_END event.
* @param {Event} event The mouseup event that triggered this method.
*/
tumbler.Dragger.prototype.onMouseUp = function(event) {
this.target_.removeEventListener('mouseup', this.boundMouseUp_, false);
this.target_.removeEventListener('mousemove', this.boundMouseMove_, false);
this.boundMouseUp_ = null;
this.boundMouseMove_ = null;
this.isDragging_ = false;
var dragEndEvent = { type: tumbler.Dragger.DragEvents.DRAG_END,
clientX: event.offsetX,
clientY: event.offsetY};
var i;
for (i = 0; i < this.listeners_.length; ++i) {
this.listeners_[i].handleEndDrag(this.target_, dragEndEvent);
}
}

View File

@@ -0,0 +1,9 @@
@echo off
setlocal
REM Relative path of CygWin
set CYGWIN=%~dp0%..\third_party\cygwin\bin
PATH=%CYGWIN%;%PATH%
python httpd.py

View File

@@ -0,0 +1,114 @@
#!/usr/bin/python
#
# Copyright (c) 2011, The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
"""A tiny web server.
This is intended to be used for testing, and only run from within the examples
directory.
"""
import BaseHTTPServer
import logging
import os
import SimpleHTTPServer
import SocketServer
import sys
import urlparse
logging.getLogger().setLevel(logging.INFO)
# Using 'localhost' means that we only accept connections
# via the loop back interface.
SERVER_PORT = 5103
SERVER_HOST = ''
# We only run from the examples directory (the one that contains scons-out), so
# that not too much is exposed via this HTTP server. Everything in the
# directory is served, so there should never be anything potentially sensitive
# in the serving directory, especially if the machine might be a
# multi-user machine and not all users are trusted. We only serve via
# the loopback interface.
SAFE_DIR_COMPONENTS = ['bin_html']
SAFE_DIR_SUFFIX = apply(os.path.join, SAFE_DIR_COMPONENTS)
def SanityCheckDirectory():
if os.getcwd().endswith(SAFE_DIR_SUFFIX):
return
logging.error('httpd.py should only be run from the %s', SAFE_DIR_SUFFIX)
logging.error('directory for testing purposes.')
logging.error('We are currently in %s', os.getcwd())
sys.exit(1)
# An HTTP server that will quit when |is_running| is set to False. We also use
# SocketServer.ThreadingMixIn in order to handle requests asynchronously for
# faster responses.
class QuittableHTTPServer(SocketServer.ThreadingMixIn,
BaseHTTPServer.HTTPServer):
def serve_forever(self, timeout=0.5):
self.is_running = True
self.timeout = timeout
while self.is_running:
self.handle_request()
def shutdown(self):
self.is_running = False
return 1
# "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not
# exist in |str|, then the entire |str| is the key and the value is set to an
# empty string.
def KeyValuePair(str, sep='='):
if sep in str:
return str.split(sep)
else:
return [str, '']
# A small handler that looks for '?quit=1' query in the path and shuts itself
# down if it finds that parameter.
class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
(_, _, _, query, _) = urlparse.urlsplit(self.path)
url_params = dict([KeyValuePair(key_value)
for key_value in query.split('&')])
if 'quit' in url_params and '1' in url_params['quit']:
self.send_response(200, 'OK')
self.send_header('Content-type', 'text/html')
self.send_header('Content-length', '0')
self.end_headers()
self.server.shutdown()
return
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
def Run(server_address,
server_class=QuittableHTTPServer,
handler_class=QuittableHTTPHandler):
httpd = server_class(server_address, handler_class)
logging.info("Starting local server on port %d", server_address[1])
logging.info("To shut down send http://localhost:%d?quit=1",
server_address[1])
try:
httpd.serve_forever()
except KeyboardInterrupt:
logging.info("Received keyboard interrupt.")
httpd.server_close()
logging.info("Shutting down local server on port %d", server_address[1])
if __name__ == '__main__':
SanityCheckDirectory()
if len(sys.argv) > 1:
Run((SERVER_HOST, int(sys.argv[1])))
else:
Run((SERVER_HOST, SERVER_PORT))
sys.exit(0)

View File

@@ -0,0 +1,33 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<!--
Copyright (c) 2011 The Native Client Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<head>
<title>Interactive Cube Example</title>
<script type="text/javascript">
// Provide the tumbler namespace
tumbler = {};
</script>
<script type="text/javascript" src="bind.js"></script>
<script type="text/javascript" src="dragger.js"></script>
<script type="text/javascript" src="tumbler.js"></script>
<script type="text/javascript" src="vector3.js"></script>
<script type="text/javascript" src="trackball.js"></script>
</head>
<body id="bodyId">
<h1>Interactive Cube Example</h1>
<p>
The Native Client module executed in this page draws a 3D cube
and allows you to rotate it using a virtual trackball method.
</p>
<div id="tumbler_view"></div>
<script type="text/javascript">
tumbler.application = new tumbler.Application();
tumbler.application.run('tumbler_view');
</script>
</body>
</HTML>

View File

@@ -0,0 +1,296 @@
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Implement a virtual trackball in the tumbler.Trackball
* class. This class maps 2D mouse events to 3D rotations by simulating a
* trackball that you roll by dragging the mouse. There are two principle
* methods in the class: startAtPointInFrame which you use to begin a trackball
* simulation and rollToPoint, which you use while dragging the mouse. The
* rollToPoint method returns a rotation expressed as a quaternion.
*/
// Requires tumbler.Application
// Requires tumbler.DragEvent
// Requires tumbler.Vector3
/**
* Constructor for the Trackball object. This class maps 2D mouse drag events
* into 3D rotations by simulating a trackball. The idea is to simulate
* clicking on the trackball, and then rolling it as you drag the mouse.
* The math behind the trackball is simple: start with a vector from the first
* mouse-click on the ball to the center of the 3D view. At the same time, set
* the radius of the ball to be the smaller dimension of the 3D view. As you
* drag the mouse around in the 3D view, a second vector is computed from the
* surface of the ball to the center. The axis of rotation is the cross
* product of these two vectors, and the angle of rotation is the angle between
* the two vectors.
* @constructor
*/
tumbler.Trackball = function() {
/**
* The square of the trackball's radius. The math never looks at the radius,
* but looks at the radius squared.
* @type {number}
* @private
*/
this.sqrRadius_ = 0;
/**
* The 3D vector representing the point on the trackball where the mouse
* was clicked. Default is pointing stright through the center of the ball.
* @type {Object}
* @private
*/
this.rollStart_ = new tumbler.Vector3(0, 0, 1);
/**
* The 2D center of the frame that encloses the trackball.
* @type {!Object}
* @private
*/
this.center_ = { x: 0, y: 0 };
/**
* Cached camera orientation. When a drag START event happens this is set to
* the current orientation in the calling view's plugin. The default is the
* identity quaternion.
* @type {Array.<number>}
* @private
*/
this.cameraOrientation_ = [0, 0, 0, 1];
};
/**
* Compute the dimensions of the virtual trackball to fit inside |frameSize|.
* The radius of the trackball is set to be 1/2 of the smaller of the two frame
* dimensions, the center point is at the midpoint of each side.
* @param {!goog.math.Size} frameSize 2D-point representing the size of the
* element that encloses the virtual trackball.
* @private
*/
tumbler.Trackball.prototype.initInFrame_ = function(frameSize) {
// Compute the radius of the virtual trackball. This is 1/2 of the smaller
// of the frame's width and height.
var halfFrameSize = 0.5 * Math.min(frameSize.width, frameSize.height);
// Cache the square of the trackball's radius.
this.sqrRadius_ = halfFrameSize * halfFrameSize;
// Figure the center of the view.
this.center_.x = frameSize.width * 0.5;
this.center_.y = frameSize.height * 0.5;
};
/**
* Method to convert (by translation) a 2D client point from a coordinate space
* with origin in the lower-left corner of the client view to a space with
* origin in the center of the client view. Use this method before mapping the
* 2D point to he 3D tackball point (see also the projectOnTrackball_() method).
* Call the startAtPointInFrame before calling this method so that the
* |center_| property is correctly initialized.
* @param {!Object} clientPoint map this point to the coordinate space with
* origin in thecenter of the client view.
* @return {Object} the converted point.
* @private
*/
tumbler.Trackball.prototype.convertClientPoint_ = function(clientPoint) {
var difference = { x: clientPoint.x - this.center_.x,
y: clientPoint.y - this.center_.y }
return difference;
};
/**
* Method to map a 2D point to a 3D point on the virtual trackball that was set
* up using the startAtPointInFrame method. If the point lies outside of the
* radius of the virtual trackball, then the z-coordinate of the 3D point
* is set to 0.
* @param {!Object.<x, y>} point 2D-point in the coordinate space with origin
* in the center of the client view.
* @return {tumbler.Vector3} the 3D point on the virtual trackball.
* @private
*/
tumbler.Trackball.prototype.projectOnTrackball_ = function(point) {
var sqrRadius2D = point.x * point.x + point.y * point.y;
var zValue;
if (sqrRadius2D > this.sqrRadius_) {
// |point| lies outside the virtual trackball's sphere, so use a virtual
// z-value of 0. This is equivalent to clicking on the horizontal equator
// of the trackball.
zValue = 0;
} else {
// A sphere can be defined as: r^2 = x^2 + y^2 + z^2, so z =
// sqrt(r^2 - (x^2 + y^2)).
zValue = Math.sqrt(this.sqrRadius_ - sqrRadius2D);
}
var trackballPoint = new tumbler.Vector3(point.x, point.y, zValue);
return trackballPoint;
};
/**
* Method to start up the trackball. The trackball works by pretending that a
* ball encloses the 3D view. You roll this pretend ball with the mouse. For
* example, if you click on the center of the ball and move the mouse straight
* to the right, you roll the ball around its Y-axis. This produces a Y-axis
* rotation. You can click on the "edge" of the ball and roll it around
* in a circle to get a Z-axis rotation.
* @param {!Object.<x, y>} startPoint 2D-point, usually the mouse-down
* point.
* @param {!Object.<width, height>} frameSize 2D-point representing the size of
* the element that encloses the virtual trackball.
*/
tumbler.Trackball.prototype.startAtPointInFrame =
function(startPoint, frameSize) {
this.initInFrame_(frameSize);
// Compute the starting vector from the surface of the ball to its center.
this.rollStart_ = this.projectOnTrackball_(
this.convertClientPoint_(startPoint));
};
/**
* Method to roll the virtual trackball; call this in response to a mouseDrag
* event. Takes |dragPoint| and projects it from 2D mouse coordinates onto the
* virtual track ball that was set up in startAtPointInFrame method.
* Returns a quaternion that represents the rotation from |rollStart_| to
* |rollEnd_|.
* @param {!Object.<x, y>} dragPoint 2D-point representing the
* destination mouse point.
* @return {Array.<number>} a quaternion that represents the rotation from
* the point wnere the mouse was clicked on the trackball to this point.
* The quaternion looks like this: [[v], cos(angle/2)], where [v] is the
* imaginary part of the quaternion and is computed as [x, y, z] *
* sin(angle/2).
*/
tumbler.Trackball.prototype.rollToPoint = function(dragPoint) {
var rollTo = this.convertClientPoint_(dragPoint);
if ((Math.abs(this.rollStart_.x - rollTo.x) <
tumbler.Trackball.DOUBLE_EPSILON) &&
(Math.abs(this.rollStart_.y, rollTo.y) <
tumbler.Trackball.DOUBLE_EPSILON)) {
// Not enough change in the vectors to roll the ball, return the identity
// quaternion.
return [0, 0, 0, 1];
}
// Compute the ending vector from the surface of the ball to its center.
var rollEnd = this.projectOnTrackball_(rollTo);
// Take the cross product of the two vectors. r = s X e
var rollVector = this.rollStart_.cross(rollEnd);
var invStartMag = 1.0 / this.rollStart_.magnitude();
var invEndMag = 1.0 / rollEnd.magnitude();
// cos(a) = (s . e) / (||s|| ||e||)
var cosAng = this.rollStart_.dot(rollEnd) * invStartMag * invEndMag;
// sin(a) = ||(s X e)|| / (||s|| ||e||)
var sinAng = rollVector.magnitude() * invStartMag * invEndMag;
// Build a quaternion that represents the rotation about |rollVector|.
// Use atan2 for a better angle. If you use only cos or sin, you only get
// half the possible angles, and you can end up with rotations that flip
// around near the poles.
var rollHalfAngle = Math.atan2(sinAng, cosAng) * 0.5;
rollVector.normalize();
// The quaternion looks like this: [[v], cos(angle/2)], where [v] is the
// imaginary part of the quaternion and is computed as [x, y, z] *
// sin(angle/2).
rollVector.scale(Math.sin(rollHalfAngle));
var ballQuaternion = [rollVector.x,
rollVector.y,
rollVector.z,
Math.cos(rollHalfAngle)];
return ballQuaternion;
};
/**
* Handle the drag START event: grab the current camera orientation from the
* sending view and set up the virtual trackball.
* @param {!tumbler.Application} view The view controller that called this
* method.
* @param {!tumbler.DragEvent} dragStartEvent The DRAG_START event that
* triggered this handler.
*/
tumbler.Trackball.prototype.handleStartDrag =
function(controller, dragStartEvent) {
// Cache the camera orientation. The orientations from the trackball as it
// rolls are concatenated to this orientation and pushed back into the
// plugin on the other side of the JavaScript bridge.
controller.setCameraOrientation(this.cameraOrientation_);
// Invert the y-coordinate for the trackball computations.
var frameSize = { width: controller.offsetWidth,
height: controller.offsetHeight };
var flippedY = { x: dragStartEvent.clientX,
y: frameSize.height - dragStartEvent.clientY };
this.startAtPointInFrame(flippedY, frameSize);
};
/**
* Handle the drag DRAG event: concatenate the current orientation to the
* cached orientation. Send this final value through to the GSPlugin via the
* setValueForKey() method.
* @param {!tumbler.Application} view The view controller that called this
* method.
* @param {!tumbler.DragEvent} dragEvent The DRAG event that triggered this
* handler.
*/
tumbler.Trackball.prototype.handleDrag =
function(controller, dragEvent) {
// Flip the y-coordinate so that the 2D origin is in the lower-left corner.
var frameSize = { width: controller.offsetWidth,
height: controller.offsetHeight };
var flippedY = { x: dragEvent.clientX,
y: frameSize.height - dragEvent.clientY };
controller.setCameraOrientation(
tumbler.multQuaternions(this.rollToPoint(flippedY),
this.cameraOrientation_));
};
/**
* Handle the drag END event: get the final orientation and concatenate it to
* the cached orientation.
* @param {!tumbler.Application} view The view controller that called this
* method.
* @param {!tumbler.DragEvent} dragEndEvent The DRAG_END event that triggered
* this handler.
*/
tumbler.Trackball.prototype.handleEndDrag =
function(controller, dragEndEvent) {
// Flip the y-coordinate so that the 2D origin is in the lower-left corner.
var frameSize = { width: controller.offsetWidth,
height: controller.offsetHeight };
var flippedY = { x: dragEndEvent.clientX,
y: frameSize.height - dragEndEvent.clientY };
this.cameraOrientation_ = tumbler.multQuaternions(this.rollToPoint(flippedY),
this.cameraOrientation_);
controller.setCameraOrientation(this.cameraOrientation_);
};
/**
* A utility function to multiply two quaterions. Returns the product q0 * q1.
* This is effectively the same thing as concatenating the two rotations
* represented in each quaternion together. Note that quaternion multiplication
* is NOT commutative: q0 * q1 != q1 * q0.
* @param {!Array.<number>} q0 A 4-element array representing the first
* quaternion.
* @param {!Array.<number>} q1 A 4-element array representing the second
* quaternion.
* @return {Array.<number>} A 4-element array representing the product q0 * q1.
*/
tumbler.multQuaternions = function(q0, q1) {
// Return q0 * q1 (note the order).
var qMult = [
q0[3] * q1[0] + q0[0] * q1[3] + q0[1] * q1[2] - q0[2] * q1[1],
q0[3] * q1[1] - q0[0] * q1[2] + q0[1] * q1[3] + q0[2] * q1[0],
q0[3] * q1[2] + q0[0] * q1[1] - q0[1] * q1[0] + q0[2] * q1[3],
q0[3] * q1[3] - q0[0] * q1[0] - q0[1] * q1[1] - q0[2] * q1[2]
];
return qMult;
};
/**
* Real numbers that are less than this distance apart are considered
* equivalent.
* TODO(dspringer): It seems as though there should be a const like this
* in Closure somewhere (goog.math?).
* @type {number}
*/
tumbler.Trackball.DOUBLE_EPSILON = 1.0e-16;

View File

@@ -0,0 +1,133 @@
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview The tumbler Application object. This object instantiates a
* Trackball object and connects it to the element named |tumbler_content|.
* It also conditionally embeds a debuggable module or a release module into
* the |tumbler_content| element.
*/
// Requires tumbler
// Requires tumbler.Dragger
// Requires tumbler.Trackball
/**
* Constructor for the Application class. Use the run() method to populate
* the object with controllers and wire up the events.
* @constructor
*/
tumbler.Application = function() {
/**
* The native module for the application. This refers to the module loaded
* via the <embed> tag.
* @type {Element}
* @private
*/
this.module_ = null;
/**
* The trackball object.
* @type {tumbler.Trackball}
* @private
*/
this.trackball_ = null;
/**
* The mouse-drag event object.
* @type {tumbler.Dragger}
* @private
*/
this.dragger_ = null;
/**
* The function objects that get attached as event handlers. These are
* cached so that they can be removed when they are no longer needed.
* @type {function}
* @private
*/
this.boundModuleDidLoad_ = null;
}
/**
* The ids used for elements in the DOM. The Tumlber Application expects these
* elements to exist.
* @enum {string}
* @private
*/
tumbler.Application.DomIds_ = {
MODULE: 'tumbler', // The <embed> element representing the NaCl module
VIEW: 'tumbler_view' // The <div> containing the NaCl element.
}
/**
* Called by the module loading function once the module has been loaded.
* @param {?Element} nativeModule The instance of the native module.
*/
tumbler.Application.prototype.moduleDidLoad = function() {
this.module_ = document.getElementById(tumbler.Application.DomIds_.MODULE);
// Unbind the load function.
this.boundModuleDidLoad_ = null;
/**
* Set the camera orientation property on the NaCl module.
* @param {Array.<number>} orientation A 4-element array representing the
* camera orientation as a quaternion.
*/
this.module_.setCameraOrientation = function(orientation) {
var methodString = 'setCameraOrientation ' +
'orientation:' +
JSON.stringify(orientation);
this.postMessage(methodString);
}
this.trackball_ = new tumbler.Trackball();
this.dragger_ = new tumbler.Dragger(this.module_);
this.dragger_.addDragListener(this.trackball_);
}
/**
* Asserts that cond is true; issues an alert and throws an Error otherwise.
* @param {bool} cond The condition.
* @param {String} message The error message issued if cond is false.
*/
tumbler.Application.prototype.assert = function(cond, message) {
if (!cond) {
message = "Assertion failed: " + message;
alert(message);
throw new Error(message);
}
}
/**
* The run() method starts and 'runs' the application. The trackball object
* is allocated and all the events get wired up.
* @param {?String} opt_contentDivName The id of a DOM element in which to
* embed the Native Client module. If unspecified, defaults to
* VIEW. The DOM element must exist.
*/
tumbler.Application.prototype.run = function(opt_contentDivName) {
contentDivName = opt_contentDivName || tumbler.Application.DomIds_.VIEW;
var contentDiv = document.getElementById(contentDivName);
this.assert(contentDiv, "Missing DOM element '" + contentDivName + "'");
// Note that the <EMBED> element is wrapped inside a <DIV>, which has a 'load'
// event listener attached. This method is used instead of attaching the
// 'load' event listener directly to the <EMBED> element to ensure that the
// listener is active before the NaCl module 'load' event fires.
this.boundModuleDidLoad_ = this.moduleDidLoad.bind(this);
contentDiv.addEventListener('load', this.boundModuleDidLoad_, true);
// Load the published .nexe. This includes the 'nacl' attribute which
// shows how to load multi-architecture modules. Each entry in the "nexes"
// object in the .nmf manifest file is a key-value pair: the key is the
// runtime ('x86-32', 'x86-64', etc.); the value is a URL for the desired
// NaCl module. To load the debug versions of your .nexes, set the 'nacl'
// attribute to the _dbg.nmf version of the manifest file.
contentDiv.innerHTML = '<embed id="'
+ tumbler.Application.DomIds_.MODULE + '" '
+ 'src=tumbler.nmf '
+ 'type="application/x-nacl" '
+ 'width="480" height="480" />'
}

View File

@@ -0,0 +1,6 @@
{
"program": {
"x86-64": {"url": "NativeClientTumbler_x64.exe"},
"x86-32": {"url": "NativeClientTumbler.exe"}
}
}

View File

@@ -0,0 +1,91 @@
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview A 3D vector class. Proviudes some utility functions on
* 3-dimentional vectors.
*/
// Requires tumbler
/**
* Constructor for the Vector3 object. This class contains a 3-tuple that
* represents a vector in 3D space.
* @param {?number} opt_x The x-coordinate for this vector. If null or
* undefined, the x-coordinate value is set to 0.
* @param {?number} opt_y The y-coordinate for this vector. If null or
* undefined, the y-coordinate value is set to 0.
* @param {?number} opt_z The z-coordinate for this vector. If null or
* undefined, the z-coordinate value is set to 0.
* @constructor
*/
tumbler.Vector3 = function(opt_x, opt_y, opt_z) {
/**
* The vector's 3-tuple.
* @type {number}
*/
this.x = opt_x || 0;
this.y = opt_y || 0;
this.z = opt_z || 0;
}
/**
* Method to return the magnitude of a Vector3.
* @return {number} the magnitude of the vector.
*/
tumbler.Vector3.prototype.magnitude = function() {
return Math.sqrt(this.dot(this));
}
/**
* Normalize the vector in-place.
* @return {number} the magnitude of the vector.
*/
tumbler.Vector3.prototype.normalize = function() {
var mag = this.magnitude();
if (mag < tumbler.Vector3.DOUBLE_EPSILON)
return 0.0; // |this| is equivalent to the 0-vector, don't normalize.
this.scale(1.0 / mag);
return mag;
}
/**
* Scale the vector in-place by |s|.
* @param {!number} s The scale factor.
*/
tumbler.Vector3.prototype.scale = function(s) {
this.x *= s;
this.y *= s;
this.z *= s;
}
/**
* Compute the dot product: |this| . v.
* @param {!tumbler.Vector3} v The vector to dot.
* @return {number} the result of |this| . v.
*/
tumbler.Vector3.prototype.dot = function(v) {
return this.x * v.x + this.y * v.y + this.z * v.z;
}
/**
* Compute the cross product: |this| X v.
* @param {!tumbler.Vector3} v The vector to cross with.
* @return {tumbler.Vector3} the result of |this| X v.
*/
tumbler.Vector3.prototype.cross = function(v) {
var vCross = new tumbler.Vector3(this.y * v.z - this.z * v.y,
this.z * v.x - this.x * v.z,
this.x * v.y - this.y * v.x);
return vCross;
}
/**
* Real numbers that are less than this distance apart are considered
* equivalent.
* TODO(dspringer): It seems as though there should be a const like this
* in generally available somewhere.
* @type {number}
*/
tumbler.Vector3.DOUBLE_EPSILON = 1.0e-16;