UNPKG

206 kBJavaScriptView Raw
1;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
2var chooseProtocol = require('./protocol').chooseProtocol
3 , EventEmitter = require('events').EventEmitter
4 , _ = require('underscore');
5
6var BaseConnection = module.exports = function(opts) {
7 this.opts = _.defaults(opts || {}, {
8 host : '127.0.0.1',
9 enableGestures: false,
10 port: 6437,
11 enableHeartbeat: true,
12 heartbeatInterval: 100,
13 requestProtocolVersion: 3
14 });
15 this.host = this.opts.host;
16 this.port = this.opts.port;
17 this.on('ready', function() {
18 this.enableGestures(this.opts.enableGestures);
19 if (this.opts.enableHeartbeat) this.startHeartbeat();
20 });
21 this.on('disconnect', function() {
22 if (this.opts.enableHeartbeat) this.stopHeartbeat();
23 });
24 this.heartbeatTimer = null;
25}
26
27BaseConnection.prototype.getUrl = function() {
28 return "ws://" + this.host + ":" + this.port + "/v" + this.opts.requestProtocolVersion + ".json";
29}
30
31BaseConnection.prototype.sendHeartbeat = function() {
32 if (this.protocol) {
33 this.setHeartbeatState(true);
34 this.protocol.sendHeartbeat(this);
35 }
36}
37
38BaseConnection.prototype.handleOpen = function() {
39 this.emit('connect');
40}
41
42BaseConnection.prototype.enableGestures = function(enabled) {
43 this.gesturesEnabled = enabled ? true : false;
44 this.send(this.protocol.encode({"enableGestures": this.gesturesEnabled}));
45}
46
47BaseConnection.prototype.handleClose = function() {
48 this.disconnect();
49 this.startReconnection();
50}
51
52BaseConnection.prototype.startReconnection = function() {
53 var connection = this;
54 setTimeout(function() { connection.connect() }, 1000);
55}
56
57BaseConnection.prototype.disconnect = function() {
58 if (!this.socket) return;
59 this.socket.close();
60 delete this.socket;
61 delete this.protocol;
62 this.emit('disconnect');
63}
64
65BaseConnection.prototype.handleData = function(data) {
66 var message = JSON.parse(data);
67 var messageEvent;
68 if (this.protocol === undefined) {
69 messageEvent = this.protocol = chooseProtocol(message);
70 this.emit('ready');
71 } else {
72 messageEvent = this.protocol(message);
73 }
74 this.emit(messageEvent.type, messageEvent);
75}
76
77BaseConnection.prototype.connect = function() {
78 if (this.socket) return;
79 this.socket = this.setupSocket();
80 return true;
81}
82
83BaseConnection.prototype.send = function(data) {
84 this.socket.send(data);
85}
86
87BaseConnection.prototype.stopHeartbeat = function() {
88 if (!this.heartbeatTimer) return;
89 clearInterval(this.heartbeatTimer);
90 delete this.heartbeatTimer;
91 this.setHeartbeatState(false);
92};
93
94BaseConnection.prototype.setHeartbeatState = function(state) {
95 if (this.heartbeatState === state) return;
96 this.heartbeatState = state;
97 this.emit(this.heartbeatState ? 'focus' : 'blur');
98};
99
100_.extend(BaseConnection.prototype, EventEmitter.prototype);
101
102
103},{"./protocol":12,"events":17,"underscore":20}],2:[function(require,module,exports){
104var CircularBuffer = module.exports = function(size) {
105 this.pos = 0;
106 this._buf = [];
107 this.size = size;
108}
109
110CircularBuffer.prototype.get = function(i) {
111 if (i == undefined) i = 0;
112 if (i >= this.size) return undefined;
113 if (i >= this._buf.length) return undefined;
114 return this._buf[(this.pos - i - 1) % this.size];
115}
116
117CircularBuffer.prototype.push = function(o) {
118 this._buf[this.pos % this.size] = o;
119 return this.pos++;
120}
121
122},{}],3:[function(require,module,exports){
123var Connection = module.exports = require('./base_connection')
124
125Connection.prototype.setupSocket = function() {
126 var connection = this;
127 var socket = new WebSocket(this.getUrl());
128 socket.onopen = function() { connection.handleOpen() };
129 socket.onmessage = function(message) { connection.handleData(message.data) };
130 socket.onclose = function() { connection.handleClose() };
131 return socket;
132}
133
134Connection.prototype.startHeartbeat = function() {
135 if (!this.protocol.sendHeartbeat || this.heartbeatTimer) return;
136 var connection = this;
137 var propertyName = null;
138 if (typeof document.hidden !== "undefined") {
139 propertyName = "hidden";
140 } else if (typeof document.mozHidden !== "undefined") {
141 propertyName = "mozHidden";
142 } else if (typeof document.msHidden !== "undefined") {
143 propertyName = "msHidden";
144 } else if (typeof document.webkitHidden !== "undefined") {
145 propertyName = "webkitHidden";
146 } else {
147 propertyName = undefined;
148 }
149
150 var windowVisible = true;
151
152 var focusListener = window.addEventListener('focus', function(e) { windowVisible = true; });
153 var blurListener = window.addEventListener('blur', function(e) { windowVisible = false; });
154
155 this.on('disconnect', function() {
156 if (connection.heartbeatTimer) {
157 clearTimeout(connection.heartbeatTimer);
158 delete connection.heartbeatTimer;
159 }
160 window.removeEventListener(focusListener);
161 window.removeEventListener(blurListener);
162 });
163
164 this.heartbeatTimer = setInterval(function() {
165 var isVisible = propertyName === undefined ? true : document[propertyName] === false;
166 if (isVisible && windowVisible) {
167 connection.sendHeartbeat();
168 } else {
169 connection.setHeartbeatState(false);
170 }
171 }, this.opts.heartbeatInterval);
172}
173
174},{"./base_connection":1}],4:[function(require,module,exports){
175(function(process){var Frame = require('./frame')
176 , CircularBuffer = require("./circular_buffer")
177 , Pipeline = require("./pipeline")
178 , EventEmitter = require('events').EventEmitter
179 , gestureListener = require('./gesture').gestureListener
180 , _ = require('underscore');
181
182/**
183 * Constructs a Controller object.
184 *
185 * When creating a Controller object, you may optionally pass in options
186 * to set the host , set the port, enable gestures, or select the frame event type.
187 *
188 * ```javascript
189 * var controller = new Leap.Controller({
190 * host: '127.0.0.1',
191 * port: 6437,
192 * enableGestures: true,
193 * frameEventName: 'animationFrame'
194 * });
195 * ```
196 *
197 * @class Controller
198 * @memberof Leap
199 * @classdesc
200 * The Controller class is your main interface to the Leap Motion Controller.
201 *
202 * Create an instance of this Controller class to access frames of tracking data
203 * and configuration information. Frame data can be polled at any time using the
204 * [Controller.frame]{@link Leap.Controller#frame}() function. Call frame() or frame(0) to get the most recent
205 * frame. Set the history parameter to a positive integer to access previous frames.
206 * A controller stores up to 60 frames in its frame history.
207 *
208 * Polling is an appropriate strategy for applications which already have an
209 * intrinsic update loop, such as a game.
210 */
211var Controller = module.exports = function(opts) {
212 var inNode = typeof(process) !== 'undefined' && process.title === 'node';
213
214 opts = _.defaults(opts || {}, {
215 inNode: inNode
216 });
217
218 this.inNode = opts.inNode;
219
220 opts = _.defaults(opts || {}, {
221 frameEventName: this.useAnimationLoop() ? 'animationFrame' : 'deviceFrame',
222 supressAnimationLoop: false,
223 });
224
225 this.supressAnimationLoop = opts.supressAnimationLoop;
226 this.frameEventName = opts.frameEventName;
227 this.history = new CircularBuffer(200);
228 this.lastFrame = Frame.Invalid;
229 this.lastValidFrame = Frame.Invalid;
230 this.lastConnectionFrame = Frame.Invalid;
231 this.accumulatedGestures = [];
232 if (opts.connectionType === undefined) {
233 this.connectionType = (this.inBrowser() ? require('./connection') : require('./node_connection'));
234 } else {
235 this.connectionType = opts.connectionType;
236 }
237 this.connection = new this.connectionType(opts);
238 this.setupConnectionEvents();
239}
240
241Controller.prototype.gesture = function(type, cb) {
242 var creator = gestureListener(this, type);
243 if (cb !== undefined) {
244 creator.stop(cb);
245 }
246 return creator;
247}
248
249Controller.prototype.inBrowser = function() {
250 return !this.inNode;
251}
252
253Controller.prototype.useAnimationLoop = function() {
254 return this.inBrowser() && typeof(chrome) === "undefined";
255}
256
257Controller.prototype.connect = function() {
258 var controller = this;
259 if (this.connection.connect() && this.inBrowser() && !controller.supressAnimationLoop) {
260 var callback = function() {
261 controller.emit('animationFrame', controller.lastConnectionFrame);
262 window.requestAnimFrame(callback);
263 }
264 window.requestAnimFrame(callback);
265 }
266}
267
268Controller.prototype.disconnect = function() {
269 this.connection.disconnect();
270}
271
272/**
273 * Returns a frame of tracking data from the Leap.
274 *
275 * Use the optional history parameter to specify which frame to retrieve.
276 * Call frame() or frame(0) to access the most recent frame; call frame(1) to
277 * access the previous frame, and so on. If you use a history value greater
278 * than the number of stored frames, then the controller returns an invalid frame.
279 *
280 * @method frame
281 * @memberof Leap.Controller.prototype
282 * @param {number} history The age of the frame to return, counting backwards from
283 * the most recent frame (0) into the past and up to the maximum age (59).
284 * @returns {Leap.Frame} The specified frame; or, if no history
285 * parameter is specified, the newest frame. If a frame is not available at
286 * the specified history position, an invalid Frame is returned.
287 */
288Controller.prototype.frame = function(num) {
289 return this.history.get(num) || Frame.Invalid;
290}
291
292Controller.prototype.loop = function(callback) {
293 switch (callback.length) {
294 case 1:
295 this.on(this.frameEventName, callback);
296 break;
297 case 2:
298 var controller = this;
299 var scheduler = null;
300 var immediateRunnerCallback = function(frame) {
301 callback(frame, function() {
302 if (controller.lastFrame != frame) {
303 immediateRunnerCallback(controller.lastFrame);
304 } else {
305 controller.once(controller.frameEventName, immediateRunnerCallback);
306 }
307 });
308 }
309 this.once(this.frameEventName, immediateRunnerCallback);
310 break;
311 }
312 this.connect();
313}
314
315Controller.prototype.addStep = function(step) {
316 if (!this.pipeline) this.pipeline = new Pipeline(this);
317 this.pipeline.addStep(step);
318}
319
320Controller.prototype.processFrame = function(frame) {
321 if (frame.gestures) {
322 this.accumulatedGestures = this.accumulatedGestures.concat(frame.gestures);
323 }
324 if (this.pipeline) {
325 frame = this.pipeline.run(frame);
326 if (!frame) frame = Frame.Invalid;
327 }
328 this.lastConnectionFrame = frame;
329 this.emit('deviceFrame', frame);
330}
331
332Controller.prototype.processFinishedFrame = function(frame) {
333 this.lastFrame = frame;
334 if (frame.valid) {
335 this.lastValidFrame = frame;
336 }
337 frame.controller = this;
338 frame.historyIdx = this.history.push(frame);
339 if (frame.gestures) {
340 frame.gestures = this.accumulatedGestures;
341 this.accumulatedGestures = [];
342 for (var gestureIdx = 0; gestureIdx != frame.gestures.length; gestureIdx++) {
343 this.emit("gesture", frame.gestures[gestureIdx], frame);
344 }
345 }
346 this.emit('frame', frame);
347}
348
349Controller.prototype.setupConnectionEvents = function() {
350 var controller = this;
351 this.connection.on('frame', function(frame) {
352 controller.processFrame(frame);
353 });
354 this.on(this.frameEventName, function(frame) {
355 controller.processFinishedFrame(frame);
356 });
357
358 // Delegate connection events
359 this.connection.on('disconnect', function() { controller.emit('disconnect'); });
360 this.connection.on('ready', function() { controller.emit('ready'); });
361 this.connection.on('connect', function() { controller.emit('connect'); });
362 this.connection.on('focus', function() { controller.emit('focus') });
363 this.connection.on('blur', function() { controller.emit('blur') });
364 this.connection.on('protocol', function(protocol) { controller.emit('protocol', protocol); });
365 this.connection.on('deviceConnect', function(evt) { controller.emit(evt.state ? 'deviceConnected' : 'deviceDisconnected'); });
366}
367
368_.extend(Controller.prototype, EventEmitter.prototype);
369
370})(require("__browserify_process"))
371},{"./circular_buffer":2,"./connection":3,"./frame":5,"./gesture":6,"./node_connection":16,"./pipeline":10,"__browserify_process":18,"events":17,"underscore":20}],5:[function(require,module,exports){
372var Hand = require("./hand")
373 , Pointable = require("./pointable")
374 , createGesture = require("./gesture").createGesture
375 , glMatrix = require("gl-matrix")
376 , mat3 = glMatrix.mat3
377 , vec3 = glMatrix.vec3
378 , InteractionBox = require("./interaction_box")
379 , _ = require("underscore");
380
381/**
382 * Constructs a Frame object.
383 *
384 * Frame instances created with this constructor are invalid.
385 * Get valid Frame objects by calling the
386 * [Controller.frame]{@link Leap.Controller#frame}() function.
387 *<C-D-Space>
388 * @class Frame
389 * @memberof Leap
390 * @classdesc
391 * The Frame class represents a set of hand and finger tracking data detected
392 * in a single frame.
393 *
394 * The Leap detects hands, fingers and tools within the tracking area, reporting
395 * their positions, orientations and motions in frames at the Leap frame rate.
396 *
397 * Access Frame objects using the [Controller.frame]{@link Leap.Controller#frame}() function.
398 */
399var Frame = module.exports = function(data) {
400 /**
401 * Reports whether this Frame instance is valid.
402 *
403 * A valid Frame is one generated by the Controller object that contains
404 * tracking data for all detected entities. An invalid Frame contains no
405 * actual tracking data, but you can call its functions without risk of a
406 * undefined object exception. The invalid Frame mechanism makes it more
407 * convenient to track individual data across the frame history. For example,
408 * you can invoke:
409 *
410 * ```javascript
411 * var finger = controller.frame(n).finger(fingerID);
412 * ```
413 *
414 * for an arbitrary Frame history value, "n", without first checking whether
415 * frame(n) returned a null object. (You should still check that the
416 * returned Finger instance is valid.)
417 *
418 * @member valid
419 * @memberof Leap.Frame.prototype
420 * @type {Boolean}
421 */
422 this.valid = true;
423 /**
424 * A unique ID for this Frame. Consecutive frames processed by the Leap
425 * have consecutive increasing values.
426 * @member id
427 * @memberof Leap.Frame.prototype
428 * @type {String}
429 */
430 this.id = data.id;
431 /**
432 * The frame capture time in microseconds elapsed since the Leap started.
433 * @member timestamp
434 * @memberof Leap.Frame.prototype
435 * @type {number}
436 */
437 this.timestamp = data.timestamp;
438 /**
439 * The list of Hand objects detected in this frame, given in arbitrary order.
440 * The list can be empty if no hands are detected.
441 *
442 * @member hands[]
443 * @memberof Leap.Frame.prototype
444 * @type {Leap.Hand}
445 */
446 this.hands = [];
447 this.handsMap = {};
448 /**
449 * The list of Pointable objects (fingers and tools) detected in this frame,
450 * given in arbitrary order. The list can be empty if no fingers or tools are
451 * detected.
452 *
453 * @member pointables[]
454 * @memberof Leap.Frame.prototype
455 * @type {Leap.Pointable}
456 */
457 this.pointables = [];
458 /**
459 * The list of Tool objects detected in this frame, given in arbitrary order.
460 * The list can be empty if no tools are detected.
461 *
462 * @member tools[]
463 * @memberof Leap.Frame.prototype
464 * @type {Leap.Pointable}
465 */
466 this.tools = [];
467 /**
468 * The list of Finger objects detected in this frame, given in arbitrary order.
469 * The list can be empty if no fingers are detected.
470 * @member fingers[]
471 * @memberof Leap.Frame.prototype
472 * @type {Leap.Pointable}
473 */
474 this.fingers = [];
475
476 if (data.interactionBox) {
477 this.interactionBox = new InteractionBox(data.interactionBox);
478 }
479 this.gestures = [];
480 this.pointablesMap = {};
481 this._translation = data.t;
482 this._rotation = _.flatten(data.r);
483 this._scaleFactor = data.s;
484 this.data = data;
485 this.type = 'frame'; // used by event emitting
486 this.currentFrameRate = data.currentFrameRate;
487 var handMap = {};
488 for (var handIdx = 0, handCount = data.hands.length; handIdx != handCount; handIdx++) {
489 var hand = new Hand(data.hands[handIdx]);
490 hand.frame = this;
491 this.hands.push(hand);
492 this.handsMap[hand.id] = hand;
493 handMap[hand.id] = handIdx;
494 }
495 for (var pointableIdx = 0, pointableCount = data.pointables.length; pointableIdx != pointableCount; pointableIdx++) {
496 var pointable = new Pointable(data.pointables[pointableIdx]);
497 pointable.frame = this;
498 this.pointables.push(pointable);
499 this.pointablesMap[pointable.id] = pointable;
500 (pointable.tool ? this.tools : this.fingers).push(pointable);
501 if (pointable.handId !== undefined && handMap.hasOwnProperty(pointable.handId)) {
502 var hand = this.hands[handMap[pointable.handId]];
503 hand.pointables.push(pointable);
504 (pointable.tool ? hand.tools : hand.fingers).push(pointable);
505 }
506 }
507
508 if (data.gestures) {
509 /**
510 * The list of Gesture objects detected in this frame, given in arbitrary order.
511 * The list can be empty if no gestures are detected.
512 *
513 * Circle and swipe gestures are updated every frame. Tap gestures
514 * only appear in the list for a single frame.
515 * @member gestures[]
516 * @memberof Leap.Frame.prototype
517 * @type {Leap.Gesture}
518 */
519 for (var gestureIdx = 0, gestureCount = data.gestures.length; gestureIdx != gestureCount; gestureIdx++) {
520 this.gestures.push(createGesture(data.gestures[gestureIdx]));
521 }
522 }
523}
524
525/**
526 * The tool with the specified ID in this frame.
527 *
528 * Use the Frame tool() function to retrieve a tool from
529 * this frame using an ID value obtained from a previous frame.
530 * This function always returns a Pointable object, but if no tool
531 * with the specified ID is present, an invalid Pointable object is returned.
532 *
533 * Note that ID values persist across frames, but only until tracking of a
534 * particular object is lost. If tracking of a tool is lost and subsequently
535 * regained, the new Pointable object representing that tool may have a
536 * different ID than that representing the tool in an earlier frame.
537 *
538 * @method tool
539 * @memberof Leap.Frame.prototype
540 * @param {String} id The ID value of a Tool object from a previous frame.
541 * @returns {Leap.Pointable} The tool with the
542 * matching ID if one exists in this frame; otherwise, an invalid Pointable object
543 * is returned.
544 */
545Frame.prototype.tool = function(id) {
546 var pointable = this.pointable(id);
547 return pointable.tool ? pointable : Pointable.Invalid;
548}
549
550/**
551 * The Pointable object with the specified ID in this frame.
552 *
553 * Use the Frame pointable() function to retrieve the Pointable object from
554 * this frame using an ID value obtained from a previous frame.
555 * This function always returns a Pointable object, but if no finger or tool
556 * with the specified ID is present, an invalid Pointable object is returned.
557 *
558 * Note that ID values persist across frames, but only until tracking of a
559 * particular object is lost. If tracking of a finger or tool is lost and subsequently
560 * regained, the new Pointable object representing that finger or tool may have
561 * a different ID than that representing the finger or tool in an earlier frame.
562 *
563 * @method pointable
564 * @memberof Leap.Frame.prototype
565 * @param {String} id The ID value of a Pointable object from a previous frame.
566 * @returns {Leap.Pointable} The Pointable object with
567 * the matching ID if one exists in this frame;
568 * otherwise, an invalid Pointable object is returned.
569 */
570Frame.prototype.pointable = function(id) {
571 return this.pointablesMap[id] || Pointable.Invalid;
572}
573
574/**
575 * The finger with the specified ID in this frame.
576 *
577 * Use the Frame finger() function to retrieve the finger from
578 * this frame using an ID value obtained from a previous frame.
579 * This function always returns a Finger object, but if no finger
580 * with the specified ID is present, an invalid Pointable object is returned.
581 *
582 * Note that ID values persist across frames, but only until tracking of a
583 * particular object is lost. If tracking of a finger is lost and subsequently
584 * regained, the new Pointable object representing that physical finger may have
585 * a different ID than that representing the finger in an earlier frame.
586 *
587 * @method finger
588 * @memberof Leap.Frame.prototype
589 * @param {String} id The ID value of a finger from a previous frame.
590 * @returns {Leap.Pointable} The finger with the
591 * matching ID if one exists in this frame; otherwise, an invalid Pointable
592 * object is returned.
593 */
594Frame.prototype.finger = function(id) {
595 var pointable = this.pointable(id);
596 return !pointable.tool ? pointable : Pointable.Invalid;
597}
598
599/**
600 * The Hand object with the specified ID in this frame.
601 *
602 * Use the Frame hand() function to retrieve the Hand object from
603 * this frame using an ID value obtained from a previous frame.
604 * This function always returns a Hand object, but if no hand
605 * with the specified ID is present, an invalid Hand object is returned.
606 *
607 * Note that ID values persist across frames, but only until tracking of a
608 * particular object is lost. If tracking of a hand is lost and subsequently
609 * regained, the new Hand object representing that physical hand may have
610 * a different ID than that representing the physical hand in an earlier frame.
611 *
612 * @method hand
613 * @memberof Leap.Frame.prototype
614 * @param {String} id The ID value of a Hand object from a previous frame.
615 * @returns {Leap.Hand} The Hand object with the matching
616 * ID if one exists in this frame; otherwise, an invalid Hand object is returned.
617 */
618Frame.prototype.hand = function(id) {
619 return this.handsMap[id] || Hand.Invalid;
620}
621
622/**
623 * The angle of rotation around the rotation axis derived from the overall
624 * rotational motion between the current frame and the specified frame.
625 *
626 * The returned angle is expressed in radians measured clockwise around
627 * the rotation axis (using the right-hand rule) between the start and end frames.
628 * The value is always between 0 and pi radians (0 and 180 degrees).
629 *
630 * The Leap derives frame rotation from the relative change in position and
631 * orientation of all objects detected in the field of view.
632 *
633 * If either this frame or sinceFrame is an invalid Frame object, then the
634 * angle of rotation is zero.
635 *
636 * @method rotationAngle
637 * @memberof Leap.Frame.prototype
638 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative rotation.
639 * @param {number[]} [axis] The axis to measure rotation around.
640 * @returns {number} A positive value containing the heuristically determined
641 * rotational change between the current frame and that specified in the sinceFrame parameter.
642 */
643Frame.prototype.rotationAngle = function(sinceFrame, axis) {
644 if (!this.valid || !sinceFrame.valid) return 0.0;
645
646 var rot = this.rotationMatrix(sinceFrame);
647 var cs = (rot[0] + rot[4] + rot[8] - 1.0)*0.5
648 var angle = Math.acos(cs);
649 angle = isNaN(angle) ? 0.0 : angle;
650
651 if (axis !== undefined) {
652 var rotAxis = this.rotationAxis(sinceFrame);
653 angle *= vec3.dot(rotAxis, vec3.normalize(vec3.create(), axis));
654 }
655
656 return angle;
657}
658
659/**
660 * The axis of rotation derived from the overall rotational motion between
661 * the current frame and the specified frame.
662 *
663 * The returned direction vector is normalized.
664 *
665 * The Leap derives frame rotation from the relative change in position and
666 * orientation of all objects detected in the field of view.
667 *
668 * If either this frame or sinceFrame is an invalid Frame object, or if no
669 * rotation is detected between the two frames, a zero vector is returned.
670 *
671 * @method rotationAxis
672 * @memberof Leap.Frame.prototype
673 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative rotation.
674 * @returns {number[]} A normalized direction vector representing the axis of the heuristically determined
675 * rotational change between the current frame and that specified in the sinceFrame parameter.
676 */
677Frame.prototype.rotationAxis = function(sinceFrame) {
678 if (!this.valid || !sinceFrame.valid) return vec3.create();
679 return vec3.normalize(vec3.create(), [
680 this._rotation[7] - sinceFrame._rotation[5],
681 this._rotation[2] - sinceFrame._rotation[6],
682 this._rotation[3] - sinceFrame._rotation[1]
683 ]);
684}
685
686/**
687 * The transform matrix expressing the rotation derived from the overall
688 * rotational motion between the current frame and the specified frame.
689 *
690 * The Leap derives frame rotation from the relative change in position and
691 * orientation of all objects detected in the field of view.
692 *
693 * If either this frame or sinceFrame is an invalid Frame object, then
694 * this method returns an identity matrix.
695 *
696 * @method rotationMatrix
697 * @memberof Leap.Frame.prototype
698 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative rotation.
699 * @returns {number[]} A transformation matrix containing the heuristically determined
700 * rotational change between the current frame and that specified in the sinceFrame parameter.
701 */
702Frame.prototype.rotationMatrix = function(sinceFrame) {
703 if (!this.valid || !sinceFrame.valid) return mat3.create();
704 var transpose = mat3.transpose(mat3.create(), this._rotation)
705 return mat3.multiply(mat3.create(), sinceFrame._rotation, transpose);
706}
707
708/**
709 * The scale factor derived from the overall motion between the current frame and the specified frame.
710 *
711 * The scale factor is always positive. A value of 1.0 indicates no scaling took place.
712 * Values between 0.0 and 1.0 indicate contraction and values greater than 1.0 indicate expansion.
713 *
714 * The Leap derives scaling from the relative inward or outward motion of all
715 * objects detected in the field of view (independent of translation and rotation).
716 *
717 * If either this frame or sinceFrame is an invalid Frame object, then this method returns 1.0.
718 *
719 * @method scaleFactor
720 * @memberof Leap.Frame.prototype
721 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative scaling.
722 * @returns {number} A positive value representing the heuristically determined
723 * scaling change ratio between the current frame and that specified in the sinceFrame parameter.
724 */
725Frame.prototype.scaleFactor = function(sinceFrame) {
726 if (!this.valid || !sinceFrame.valid) return 1.0;
727 return Math.exp(this._scaleFactor - sinceFrame._scaleFactor);
728}
729
730/**
731 * The change of position derived from the overall linear motion between the
732 * current frame and the specified frame.
733 *
734 * The returned translation vector provides the magnitude and direction of the
735 * movement in millimeters.
736 *
737 * The Leap derives frame translation from the linear motion of all objects
738 * detected in the field of view.
739 *
740 * If either this frame or sinceFrame is an invalid Frame object, then this
741 * method returns a zero vector.
742 *
743 * @method translation
744 * @memberof Leap.Frame.prototype
745 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative translation.
746 * @returns {number[]} A vector representing the heuristically determined change in
747 * position of all objects between the current frame and that specified in the sinceFrame parameter.
748 */
749Frame.prototype.translation = function(sinceFrame) {
750 if (!this.valid || !sinceFrame.valid) return vec3.create();
751 return vec3.subtract(vec3.create(), this._translation, sinceFrame._translation);
752}
753
754/**
755 * A string containing a brief, human readable description of the Frame object.
756 *
757 * @method toString
758 * @memberof Leap.Frame.prototype
759 * @returns {String} A brief description of this frame.
760 */
761Frame.prototype.toString = function() {
762 var str = "Frame [ id:"+this.id+" | timestamp:"+this.timestamp+" | Hand count:("+this.hands.length+") | Pointable count:("+this.pointables.length+")";
763 if (this.gestures) str += " | Gesture count:("+this.gestures.length+")";
764 str += " ]";
765 return str;
766}
767
768/**
769 * Returns a JSON-formatted string containing the hands, pointables and gestures
770 * in this frame.
771 *
772 * @method dump
773 * @memberof Leap.Frame.prototype
774 * @returns {String} A JSON-formatted string.
775 */
776Frame.prototype.dump = function() {
777 var out = '';
778 out += "Frame Info:<br/>";
779 out += this.toString();
780 out += "<br/><br/>Hands:<br/>"
781 for (var handIdx = 0, handCount = this.hands.length; handIdx != handCount; handIdx++) {
782 out += " "+ this.hands[handIdx].toString() + "<br/>";
783 }
784 out += "<br/><br/>Pointables:<br/>";
785 for (var pointableIdx = 0, pointableCount = this.pointables.length; pointableIdx != pointableCount; pointableIdx++) {
786 out += " "+ this.pointables[pointableIdx].toString() + "<br/>";
787 }
788 if (this.gestures) {
789 out += "<br/><br/>Gestures:<br/>";
790 for (var gestureIdx = 0, gestureCount = this.gestures.length; gestureIdx != gestureCount; gestureIdx++) {
791 out += " "+ this.gestures[gestureIdx].toString() + "<br/>";
792 }
793 }
794 out += "<br/><br/>Raw JSON:<br/>";
795 out += JSON.stringify(this.data);
796 return out;
797}
798
799/**
800 * An invalid Frame object.
801 *
802 * You can use this invalid Frame in comparisons testing
803 * whether a given Frame instance is valid or invalid. (You can also check the
804 * [Frame.valid]{@link Leap.Frame#valid} property.)
805 *
806 * @static
807 * @type {Leap.Frame}
808 * @name Invalid
809 * @memberof Leap.Frame
810 */
811Frame.Invalid = {
812 valid: false,
813 hands: [],
814 fingers: [],
815 tools: [],
816 gestures: [],
817 pointables: [],
818 pointable: function() { return Pointable.Invalid },
819 finger: function() { return Pointable.Invalid },
820 hand: function() { return Hand.Invalid },
821 toString: function() { return "invalid frame" },
822 dump: function() { return this.toString() },
823 rotationAngle: function() { return 0.0; },
824 rotationMatrix: function() { return mat3.create(); },
825 rotationAxis: function() { return vec3.create(); },
826 scaleFactor: function() { return 1.0; },
827 translation: function() { return vec3.create(); }
828};
829
830},{"./gesture":6,"./hand":7,"./interaction_box":9,"./pointable":11,"gl-matrix":19,"underscore":20}],6:[function(require,module,exports){
831var glMatrix = require("gl-matrix")
832 , vec3 = glMatrix.vec3
833 , EventEmitter = require('events').EventEmitter
834 , _ = require('underscore');
835
836/**
837 * Constructs a new Gesture object.
838 *
839 * An uninitialized Gesture object is considered invalid. Get valid instances
840 * of the Gesture class, which will be one of the Gesture subclasses, from a
841 * Frame object.
842 *
843 * @class Gesture
844 * @abstract
845 * @memberof Leap
846 * @classdesc
847 * The Gesture class represents a recognized movement by the user.
848 *
849 * The Leap watches the activity within its field of view for certain movement
850 * patterns typical of a user gesture or command. For example, a movement from side to
851 * side with the hand can indicate a swipe gesture, while a finger poking forward
852 * can indicate a screen tap gesture.
853 *
854 * When the Leap recognizes a gesture, it assigns an ID and adds a
855 * Gesture object to the frame gesture list. For continuous gestures, which
856 * occur over many frames, the Leap updates the gesture by adding
857 * a Gesture object having the same ID and updated properties in each
858 * subsequent frame.
859 *
860 * **Important:** Recognition for each type of gesture must be enabled;
861 * otherwise **no gestures are recognized or reported**.
862 *
863 * Subclasses of Gesture define the properties for the specific movement patterns
864 * recognized by the Leap.
865 *
866 * The Gesture subclasses for include:
867 *
868 * * CircleGesture -- A circular movement by a finger.
869 * * SwipeGesture -- A straight line movement by the hand with fingers extended.
870 * * ScreenTapGesture -- A forward tapping movement by a finger.
871 * * KeyTapGesture -- A downward tapping movement by a finger.
872 *
873 * Circle and swipe gestures are continuous and these objects can have a
874 * state of start, update, and stop.
875 *
876 * The screen tap gesture is a discrete gesture. The Leap only creates a single
877 * ScreenTapGesture object appears for each tap and it always has a stop state.
878 *
879 * Get valid Gesture instances from a Frame object. You can get a list of gestures
880 * from the Frame gestures array. You can also use the Frame gesture() method
881 * to find a gesture in the current frame using an ID value obtained in a
882 * previous frame.
883 *
884 * Gesture objects can be invalid. For example, when you get a gesture by ID
885 * using Frame.gesture(), and there is no gesture with that ID in the current
886 * frame, then gesture() returns an Invalid Gesture object (rather than a null
887 * value). Always check object validity in situations where a gesture might be
888 * invalid.
889 */
890var createGesture = exports.createGesture = function(data) {
891 var gesture;
892 switch (data.type) {
893 case 'circle':
894 gesture = new CircleGesture(data);
895 break;
896 case 'swipe':
897 gesture = new SwipeGesture(data);
898 break;
899 case 'screenTap':
900 gesture = new ScreenTapGesture(data);
901 break;
902 case 'keyTap':
903 gesture = new KeyTapGesture(data);
904 break;
905 default:
906 throw "unkown gesture type";
907 }
908 /**
909 * The gesture ID.
910 *
911 * All Gesture objects belonging to the same recognized movement share the
912 * same ID value. Use the ID value with the Frame::gesture() method to
913 * find updates related to this Gesture object in subsequent frames.
914 *
915 * @member id
916 * @memberof Leap.Gesture.prototype
917 * @type {number}
918 */
919 gesture.id = data.id;
920 /**
921 * The list of hands associated with this Gesture, if any.
922 *
923 * If no hands are related to this gesture, the list is empty.
924 *
925 * @member handIds
926 * @memberof Leap.Gesture.prototype
927 * @type {Array}
928 */
929 gesture.handIds = data.handIds;
930 /**
931 * The list of fingers and tools associated with this Gesture, if any.
932 *
933 * If no Pointable objects are related to this gesture, the list is empty.
934 *
935 * @member pointableIds
936 * @memberof Leap.Gesture.prototype
937 * @type {Array}
938 */
939 gesture.pointableIds = data.pointableIds;
940 /**
941 * The elapsed duration of the recognized movement up to the
942 * frame containing this Gesture object, in microseconds.
943 *
944 * The duration reported for the first Gesture in the sequence (with the
945 * start state) will typically be a small positive number since
946 * the movement must progress far enough for the Leap to recognize it as
947 * an intentional gesture.
948 *
949 * @member duration
950 * @memberof Leap.Gesture.prototype
951 * @type {number}
952 */
953 gesture.duration = data.duration;
954 /**
955 * The gesture ID.
956 *
957 * Recognized movements occur over time and have a beginning, a middle,
958 * and an end. The 'state()' attribute reports where in that sequence this
959 * Gesture object falls.
960 *
961 * Possible values for the state field are:
962 *
963 * * start
964 * * update
965 * * stop
966 *
967 * @member state
968 * @memberof Leap.Gesture.prototype
969 * @type {String}
970 */
971 gesture.state = data.state;
972 /**
973 * The gesture type.
974 *
975 * Possible values for the type field are:
976 *
977 * * circle
978 * * swipe
979 * * screenTap
980 * * keyTap
981 *
982 * @member type
983 * @memberof Leap.Gesture.prototype
984 * @type {String}
985 */
986 gesture.type = data.type;
987 return gesture;
988}
989
990var gestureListener = exports.gestureListener = function(controller, type) {
991 var handlers = {};
992 var gestureMap = {};
993
994 var gestureCreator = function() {
995 var candidateGesture = gestureMap[gesture.id];
996 if (candidateGesture !== undefined) gesture.update(gesture, frame);
997 if (gesture.state == "start" || gesture.state == "stop") {
998 if (type == gesture.type && gestureMap[gesture.id] === undefined) {
999 gestureMap[gesture.id] = new Gesture(gesture, frame);
1000 gesture.update(gesture, frame);
1001 }
1002 if (gesture.state == "stop") {
1003 delete gestureMap[gesture.id];
1004 }
1005 }
1006 };
1007
1008 controller.on('gesture', function(gesture, frame) {
1009 if (gesture.type == type) {
1010 if (gesture.state == "start" || gesture.state == "stop") {
1011 if (gestureMap[gesture.id] === undefined) {
1012 var gestureTracker = new Gesture(gesture, frame);
1013 gestureMap[gesture.id] = gestureTracker;
1014 _.each(handlers, function(cb, name) {
1015 gestureTracker.on(name, cb);
1016 });
1017 }
1018 }
1019 gestureMap[gesture.id].update(gesture, frame);
1020 if (gesture.state == "stop") {
1021 delete gestureMap[gesture.id];
1022 }
1023 }
1024 });
1025 var builder = {
1026 start: function(cb) {
1027 handlers['start'] = cb;
1028 return builder;
1029 },
1030 stop: function(cb) {
1031 handlers['stop'] = cb;
1032 return builder;
1033 },
1034 complete: function(cb) {
1035 handlers['stop'] = cb;
1036 return builder;
1037 },
1038 update: function(cb) {
1039 handlers['update'] = cb;
1040 return builder;
1041 }
1042 }
1043 return builder;
1044}
1045
1046var Gesture = exports.Gesture = function(gesture, frame) {
1047 this.gestures = [gesture];
1048 this.frames = [frame];
1049}
1050
1051Gesture.prototype.update = function(gesture, frame) {
1052 this.gestures.push(gesture);
1053 this.frames.push(frame);
1054 this.emit(gesture.state, this);
1055}
1056
1057_.extend(Gesture.prototype, EventEmitter.prototype);
1058
1059/**
1060 * Constructs a new CircleGesture object.
1061 *
1062 * An uninitialized CircleGesture object is considered invalid. Get valid instances
1063 * of the CircleGesture class from a Frame object.
1064 *
1065 * @class CircleGesture
1066 * @memberof Leap
1067 * @augments Leap.Gesture
1068 * @classdesc
1069 * The CircleGesture classes represents a circular finger movement.
1070 *
1071 * A circle movement is recognized when the tip of a finger draws a circle
1072 * within the Leap field of view.
1073 *
1074 * ![CircleGesture](images/Leap_Gesture_Circle.png)
1075 *
1076 * Circle gestures are continuous. The CircleGesture objects for the gesture have
1077 * three possible states:
1078 *
1079 * * start -- The circle gesture has just started. The movement has
1080 * progressed far enough for the recognizer to classify it as a circle.
1081 * * update -- The circle gesture is continuing.
1082 * * stop -- The circle gesture is finished.
1083 */
1084var CircleGesture = function(data) {
1085 /**
1086 * The center point of the circle within the Leap frame of reference.
1087 *
1088 * @member center
1089 * @memberof Leap.CircleGesture.prototype
1090 * @type {number[]}
1091 */
1092 this.center = data.center;
1093 /**
1094 * The normal vector for the circle being traced.
1095 *
1096 * If you draw the circle clockwise, the normal vector points in the same
1097 * general direction as the pointable object drawing the circle. If you draw
1098 * the circle counterclockwise, the normal points back toward the
1099 * pointable. If the angle between the normal and the pointable object
1100 * drawing the circle is less than 90 degrees, then the circle is clockwise.
1101 *
1102 * ```javascript
1103 * var clockwiseness;
1104 * if (circle.pointable.direction.angleTo(circle.normal) <= PI/4) {
1105 * clockwiseness = "clockwise";
1106 * }
1107 * else
1108 * {
1109 * clockwiseness = "counterclockwise";
1110 * }
1111 * ```
1112 *
1113 * @member normal
1114 * @memberof Leap.CircleGesture.prototype
1115 * @type {number[]}
1116 */
1117 this.normal = data.normal;
1118 /**
1119 * The number of times the finger tip has traversed the circle.
1120 *
1121 * Progress is reported as a positive number of the number. For example,
1122 * a progress value of .5 indicates that the finger has gone halfway
1123 * around, while a value of 3 indicates that the finger has gone around
1124 * the the circle three times.
1125 *
1126 * Progress starts where the circle gesture began. Since the circle
1127 * must be partially formed before the Leap can recognize it, progress
1128 * will be greater than zero when a circle gesture first appears in the
1129 * frame.
1130 *
1131 * @member progress
1132 * @memberof Leap.CircleGesture.prototype
1133 * @type {number}
1134 */
1135 this.progress = data.progress;
1136 /**
1137 * The radius of the circle in mm.
1138 *
1139 * @member radius
1140 * @memberof Leap.CircleGesture.prototype
1141 * @type {number}
1142 */
1143 this.radius = data.radius;
1144}
1145
1146CircleGesture.prototype.toString = function() {
1147 return "CircleGesture ["+JSON.stringify(this)+"]";
1148}
1149
1150/**
1151 * Constructs a new SwipeGesture object.
1152 *
1153 * An uninitialized SwipeGesture object is considered invalid. Get valid instances
1154 * of the SwipeGesture class from a Frame object.
1155 *
1156 * @class SwipeGesture
1157 * @memberof Leap
1158 * @augments Leap.Gesture
1159 * @classdesc
1160 * The SwipeGesture class represents a swiping motion of a finger or tool.
1161 *
1162 * ![SwipeGesture](images/Leap_Gesture_Swipe.png)
1163 *
1164 * Swipe gestures are continuous.
1165 */
1166var SwipeGesture = function(data) {
1167 /**
1168 * The starting position within the Leap frame of
1169 * reference, in mm.
1170 *
1171 * @member startPosition
1172 * @memberof Leap.SwipeGesture.prototype
1173 * @type {number[]}
1174 */
1175 this.startPosition = data.startPosition;
1176 /**
1177 * The current swipe position within the Leap frame of
1178 * reference, in mm.
1179 *
1180 * @member position
1181 * @memberof Leap.SwipeGesture.prototype
1182 * @type {number[]}
1183 */
1184 this.position = data.position;
1185 /**
1186 * The unit direction vector parallel to the swipe motion.
1187 *
1188 * You can compare the components of the vector to classify the swipe as
1189 * appropriate for your application. For example, if you are using swipes
1190 * for two dimensional scrolling, you can compare the x and y values to
1191 * determine if the swipe is primarily horizontal or vertical.
1192 *
1193 * @member direction
1194 * @memberof Leap.SwipeGesture.prototype
1195 * @type {number[]}
1196 */
1197 this.direction = data.direction;
1198 /**
1199 * The speed of the finger performing the swipe gesture in
1200 * millimeters per second.
1201 *
1202 * @member speed
1203 * @memberof Leap.SwipeGesture.prototype
1204 * @type {number}
1205 */
1206 this.speed = data.speed;
1207}
1208
1209SwipeGesture.prototype.toString = function() {
1210 return "SwipeGesture ["+JSON.stringify(this)+"]";
1211}
1212
1213/**
1214 * Constructs a new ScreenTapGesture object.
1215 *
1216 * An uninitialized ScreenTapGesture object is considered invalid. Get valid instances
1217 * of the ScreenTapGesture class from a Frame object.
1218 *
1219 * @class ScreenTapGesture
1220 * @memberof Leap
1221 * @augments Leap.Gesture
1222 * @classdesc
1223 * The ScreenTapGesture class represents a tapping gesture by a finger or tool.
1224 *
1225 * A screen tap gesture is recognized when the tip of a finger pokes forward
1226 * and then springs back to approximately the original postion, as if
1227 * tapping a vertical screen. The tapping finger must pause briefly before beginning the tap.
1228 *
1229 * ![ScreenTap](images/Leap_Gesture_Tap2.png)
1230 *
1231 * ScreenTap gestures are discrete. The ScreenTapGesture object representing a tap always
1232 * has the state, STATE_STOP. Only one ScreenTapGesture object is created for each
1233 * screen tap gesture recognized.
1234 */
1235var ScreenTapGesture = function(data) {
1236 /**
1237 * The position where the screen tap is registered.
1238 *
1239 * @member position
1240 * @memberof Leap.ScreenTapGesture.prototype
1241 * @type {number[]}
1242 */
1243 this.position = data.position;
1244 /**
1245 * The direction of finger tip motion.
1246 *
1247 * @member direction
1248 * @memberof Leap.ScreenTapGesture.prototype
1249 * @type {number[]}
1250 */
1251 this.direction = data.direction;
1252 /**
1253 * The progess value is always 1.0 for a screen tap gesture.
1254 *
1255 * @member progress
1256 * @memberof Leap.ScreenTapGesture.prototype
1257 * @type {number}
1258 */
1259 this.progress = data.progress;
1260}
1261
1262ScreenTapGesture.prototype.toString = function() {
1263 return "ScreenTapGesture ["+JSON.stringify(this)+"]";
1264}
1265
1266/**
1267 * Constructs a new KeyTapGesture object.
1268 *
1269 * An uninitialized KeyTapGesture object is considered invalid. Get valid instances
1270 * of the KeyTapGesture class from a Frame object.
1271 *
1272 * @class KeyTapGesture
1273 * @memberof Leap
1274 * @augments Leap.Gesture
1275 * @classdesc
1276 * The KeyTapGesture class represents a tapping gesture by a finger or tool.
1277 *
1278 * A key tap gesture is recognized when the tip of a finger rotates down toward the
1279 * palm and then springs back to approximately the original postion, as if
1280 * tapping. The tapping finger must pause briefly before beginning the tap.
1281 *
1282 * ![KeyTap](images/Leap_Gesture_Tap.png)
1283 *
1284 * Key tap gestures are discrete. The KeyTapGesture object representing a tap always
1285 * has the state, STATE_STOP. Only one KeyTapGesture object is created for each
1286 * key tap gesture recognized.
1287 */
1288var KeyTapGesture = function(data) {
1289 /**
1290 * The position where the key tap is registered.
1291 *
1292 * @member position
1293 * @memberof Leap.KeyTapGesture.prototype
1294 * @type {number[]}
1295 */
1296 this.position = data.position;
1297 /**
1298 * The direction of finger tip motion.
1299 *
1300 * @member direction
1301 * @memberof Leap.KeyTapGesture.prototype
1302 * @type {number[]}
1303 */
1304 this.direction = data.direction;
1305 /**
1306 * The progess value is always 1.0 for a key tap gesture.
1307 *
1308 * @member progress
1309 * @memberof Leap.KeyTapGesture.prototype
1310 * @type {number}
1311 */
1312 this.progress = data.progress;
1313}
1314
1315KeyTapGesture.prototype.toString = function() {
1316 return "KeyTapGesture ["+JSON.stringify(this)+"]";
1317}
1318
1319},{"events":17,"gl-matrix":19,"underscore":20}],7:[function(require,module,exports){
1320var Pointable = require("./pointable")
1321 , glMatrix = require("gl-matrix")
1322 , mat3 = glMatrix.mat3
1323 , vec3 = glMatrix.vec3
1324 , _ = require("underscore");
1325
1326/**
1327 * Constructs a Hand object.
1328 *
1329 * An uninitialized hand is considered invalid.
1330 * Get valid Hand objects from a Frame object.
1331 * @class Hand
1332 * @memberof Leap
1333 * @classdesc
1334 * The Hand class reports the physical characteristics of a detected hand.
1335 *
1336 * Hand tracking data includes a palm position and velocity; vectors for
1337 * the palm normal and direction to the fingers; properties of a sphere fit
1338 * to the hand; and lists of the attached fingers and tools.
1339 *
1340 * Note that Hand objects can be invalid, which means that they do not contain
1341 * valid tracking data and do not correspond to a physical entity. Invalid Hand
1342 * objects can be the result of asking for a Hand object using an ID from an
1343 * earlier frame when no Hand objects with that ID exist in the current frame.
1344 * A Hand object created from the Hand constructor is also invalid.
1345 * Test for validity with the [Hand.valid]{@link Leap.Hand#valid} property.
1346 */
1347var Hand = module.exports = function(data) {
1348 /**
1349 * A unique ID assigned to this Hand object, whose value remains the same
1350 * across consecutive frames while the tracked hand remains visible. If
1351 * tracking is lost (for example, when a hand is occluded by another hand
1352 * or when it is withdrawn from or reaches the edge of the Leap field of view),
1353 * the Leap may assign a new ID when it detects the hand in a future frame.
1354 *
1355 * Use the ID value with the {@link Frame.hand}() function to find this
1356 * Hand object in future frames.
1357 *
1358 * @member id
1359 * @memberof Leap.Hand.prototype
1360 * @type {String}
1361 */
1362 this.id = data.id;
1363 /**
1364 * The center position of the palm in millimeters from the Leap origin.
1365 * @member palmPosition
1366 * @memberof Leap.Hand.prototype
1367 * @type {number[]}
1368 */
1369 this.palmPosition = data.palmPosition;
1370 /**
1371 * The direction from the palm position toward the fingers.
1372 *
1373 * The direction is expressed as a unit vector pointing in the same
1374 * direction as the directed line from the palm position to the fingers.
1375 *
1376 * @member direction
1377 * @memberof Leap.Hand.prototype
1378 * @type {number[]}
1379 */
1380 this.direction = data.direction;
1381 /**
1382 * The rate of change of the palm position in millimeters/second.
1383 *
1384 * @member palmVeclocity
1385 * @memberof Leap.Hand.prototype
1386 * @type {number[]}
1387 */
1388 this.palmVelocity = data.palmVelocity;
1389 /**
1390 * The normal vector to the palm. If your hand is flat, this vector will
1391 * point downward, or "out" of the front surface of your palm.
1392 *
1393 * ![Palm Vectors](images/Leap_Palm_Vectors.png)
1394 *
1395 * The direction is expressed as a unit vector pointing in the same
1396 * direction as the palm normal (that is, a vector orthogonal to the palm).
1397 * @member palmNormal
1398 * @memberof Leap.Hand.prototype
1399 * @type {number[]}
1400 */
1401 this.palmNormal = data.palmNormal;
1402 /**
1403 * The center of a sphere fit to the curvature of this hand.
1404 *
1405 * This sphere is placed roughly as if the hand were holding a ball.
1406 *
1407 * ![Hand Ball](images/Leap_Hand_Ball.png)
1408 * @member sphereCenter
1409 * @memberof Leap.Hand.prototype
1410 * @type {number[]}
1411 */
1412 this.sphereCenter = data.sphereCenter;
1413 /**
1414 * The radius of a sphere fit to the curvature of this hand, in millimeters.
1415 *
1416 * This sphere is placed roughly as if the hand were holding a ball. Thus the
1417 * size of the sphere decreases as the fingers are curled into a fist.
1418 *
1419 * @member sphereRadius
1420 * @memberof Leap.Hand.prototype
1421 * @type {number}
1422 */
1423 this.sphereRadius = data.sphereRadius;
1424 /**
1425 * Reports whether this is a valid Hand object.
1426 *
1427 * @member valid
1428 * @memberof Leap.Hand.prototype
1429 * @type {boolean}
1430 */
1431 this.valid = true;
1432 /**
1433 * The list of Pointable objects (fingers and tools) detected in this frame
1434 * that are associated with this hand, given in arbitrary order. The list
1435 * can be empty if no fingers or tools associated with this hand are detected.
1436 *
1437 * Use the {@link Pointable} tool property to determine
1438 * whether or not an item in the list represents a tool or finger.
1439 * You can also get only the tools using the Hand.tools[] list or
1440 * only the fingers using the Hand.fingers[] list.
1441 *
1442 * @member pointables[]
1443 * @memberof Leap.Hand.prototype
1444 * @type {Leap.Pointable[]}
1445 */
1446 this.pointables = [];
1447 /**
1448 * The list of fingers detected in this frame that are attached to
1449 * this hand, given in arbitrary order.
1450 *
1451 * The list can be empty if no fingers attached to this hand are detected.
1452 *
1453 * @member fingers[]
1454 * @memberof Leap.Hand.prototype
1455 * @type {Leap.Pointable[]}
1456 */
1457 this.fingers = [];
1458 /**
1459 * The list of tools detected in this frame that are held by this
1460 * hand, given in arbitrary order.
1461 *
1462 * The list can be empty if no tools held by this hand are detected.
1463 *
1464 * @member tools[]
1465 * @memberof Leap.Hand.prototype
1466 * @type {Leap.Pointable[]}
1467 */
1468 this.tools = [];
1469 this._translation = data.t;
1470 this._rotation = _.flatten(data.r);
1471 this._scaleFactor = data.s;
1472
1473 /**
1474 * Time the hand has been visible in seconds.
1475 *
1476 * @member Hand.prototype.timeVisible {float}
1477 */
1478 this.timeVisible = data.timeVisible;
1479
1480 /**
1481 * The palm position with stabalization
1482 * @member stabilizedPalmPosition
1483 * @memberof Leap.Hand.prototype
1484 * @type {number[]}
1485 */
1486 this.stabilizedPalmPosition = data.stabilizedPalmPosition;
1487}
1488
1489/**
1490 * The finger with the specified ID attached to this hand.
1491 *
1492 * Use this function to retrieve a Pointable object representing a finger
1493 * attached to this hand using an ID value obtained from a previous frame.
1494 * This function always returns a Pointable object, but if no finger
1495 * with the specified ID is present, an invalid Pointable object is returned.
1496 *
1497 * Note that the ID values assigned to fingers persist across frames, but only
1498 * until tracking of a particular finger is lost. If tracking of a finger is
1499 * lost and subsequently regained, the new Finger object representing that
1500 * finger may have a different ID than that representing the finger in an
1501 * earlier frame.
1502 *
1503 * @method finger
1504 * @memberof Leap.Hand.prototype
1505 * @param {String} id The ID value of a finger from a previous frame.
1506 * @returns {Leap.Pointable} The Finger object with
1507 * the matching ID if one exists for this hand in this frame; otherwise, an
1508 * invalid Finger object is returned.
1509 */
1510Hand.prototype.finger = function(id) {
1511 var finger = this.frame.finger(id);
1512 return (finger && finger.handId == this.id) ? finger : Pointable.Invalid;
1513}
1514
1515/**
1516 * The angle of rotation around the rotation axis derived from the change in
1517 * orientation of this hand, and any associated fingers and tools, between the
1518 * current frame and the specified frame.
1519 *
1520 * The returned angle is expressed in radians measured clockwise around the
1521 * rotation axis (using the right-hand rule) between the start and end frames.
1522 * The value is always between 0 and pi radians (0 and 180 degrees).
1523 *
1524 * If a corresponding Hand object is not found in sinceFrame, or if either
1525 * this frame or sinceFrame are invalid Frame objects, then the angle of rotation is zero.
1526 *
1527 * @method rotationAngle
1528 * @memberof Leap.Hand.prototype
1529 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative rotation.
1530 * @param {numnber[]} [axis] The axis to measure rotation around.
1531 * @returns {number} A positive value representing the heuristically determined
1532 * rotational change of the hand between the current frame and that specified in
1533 * the sinceFrame parameter.
1534 */
1535Hand.prototype.rotationAngle = function(sinceFrame, axis) {
1536 if (!this.valid || !sinceFrame.valid) return 0.0;
1537 var sinceHand = sinceFrame.hand(this.id);
1538 if(!sinceHand.valid) return 0.0;
1539 var rot = this.rotationMatrix(sinceFrame);
1540 var cs = (rot[0] + rot[4] + rot[8] - 1.0)*0.5
1541 var angle = Math.acos(cs);
1542 angle = isNaN(angle) ? 0.0 : angle;
1543 if (axis !== undefined) {
1544 var rotAxis = this.rotationAxis(sinceFrame);
1545 angle *= vec3.dot(rotAxis, vec3.normalize(vec3.create(), axis));
1546 }
1547 return angle;
1548}
1549
1550/**
1551 * The axis of rotation derived from the change in orientation of this hand, and
1552 * any associated fingers and tools, between the current frame and the specified frame.
1553 *
1554 * The returned direction vector is normalized.
1555 *
1556 * If a corresponding Hand object is not found in sinceFrame, or if either
1557 * this frame or sinceFrame are invalid Frame objects, then this method returns a zero vector.
1558 *
1559 * @method rotationAxis
1560 * @memberof Leap.Hand.prototype
1561 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative rotation.
1562 * @returns {number[]} A normalized direction Vector representing the axis of the heuristically determined
1563 * rotational change of the hand between the current frame and that specified in the sinceFrame parameter.
1564 */
1565Hand.prototype.rotationAxis = function(sinceFrame) {
1566 if (!this.valid || !sinceFrame.valid) return vec3.create();
1567 var sinceHand = sinceFrame.hand(this.id);
1568 if (!sinceHand.valid) return vec3.create();
1569 return vec3.normalize(vec3.create(), [
1570 this._rotation[7] - sinceHand._rotation[5],
1571 this._rotation[2] - sinceHand._rotation[6],
1572 this._rotation[3] - sinceHand._rotation[1]
1573 ]);
1574}
1575
1576/**
1577 * The transform matrix expressing the rotation derived from the change in
1578 * orientation of this hand, and any associated fingers and tools, between
1579 * the current frame and the specified frame.
1580 *
1581 * If a corresponding Hand object is not found in sinceFrame, or if either
1582 * this frame or sinceFrame are invalid Frame objects, then this method returns
1583 * an identity matrix.
1584 *
1585 * @method rotationMatrix
1586 * @memberof Leap.Hand.prototype
1587 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative rotation.
1588 * @returns {number[]} A transformation Matrix containing the heuristically determined
1589 * rotational change of the hand between the current frame and that specified in the sinceFrame parameter.
1590 */
1591Hand.prototype.rotationMatrix = function(sinceFrame) {
1592 if (!this.valid || !sinceFrame.valid) return mat3.create();
1593 var sinceHand = sinceFrame.hand(this.id);
1594 if(!sinceHand.valid) return mat3.create();
1595 var transpose = mat3.transpose(mat3.create(), this._rotation);
1596 var m = mat3.multiply(mat3.create(), sinceHand._rotation, transpose);
1597 return m;
1598}
1599
1600/**
1601 * The scale factor derived from the hand's motion between the current frame and the specified frame.
1602 *
1603 * The scale factor is always positive. A value of 1.0 indicates no scaling took place.
1604 * Values between 0.0 and 1.0 indicate contraction and values greater than 1.0 indicate expansion.
1605 *
1606 * The Leap derives scaling from the relative inward or outward motion of a hand
1607 * and its associated fingers and tools (independent of translation and rotation).
1608 *
1609 * If a corresponding Hand object is not found in sinceFrame, or if either this frame or sinceFrame
1610 * are invalid Frame objects, then this method returns 1.0.
1611 *
1612 * @method scaleFactor
1613 * @memberof Leap.Hand.prototype
1614 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative scaling.
1615 * @returns {number} A positive value representing the heuristically determined
1616 * scaling change ratio of the hand between the current frame and that specified in the sinceFrame parameter.
1617 */
1618Hand.prototype.scaleFactor = function(sinceFrame) {
1619 if (!this.valid || !sinceFrame.valid) return 1.0;
1620 var sinceHand = sinceFrame.hand(this.id);
1621 if(!sinceHand.valid) return 1.0;
1622
1623 return Math.exp(this._scaleFactor - sinceHand._scaleFactor);
1624}
1625
1626/**
1627 * The change of position of this hand between the current frame and the specified frame
1628 *
1629 * The returned translation vector provides the magnitude and direction of the
1630 * movement in millimeters.
1631 *
1632 * If a corresponding Hand object is not found in sinceFrame, or if either this frame or
1633 * sinceFrame are invalid Frame objects, then this method returns a zero vector.
1634 *
1635 * @method translation
1636 * @memberof Leap.Hand.prototype
1637 * @param {Leap.Frame} sinceFrame The starting frame for computing the relative translation.
1638 * @returns {number[]} A Vector representing the heuristically determined change in hand
1639 * position between the current frame and that specified in the sinceFrame parameter.
1640 */
1641Hand.prototype.translation = function(sinceFrame) {
1642 if (!this.valid || !sinceFrame.valid) return vec3.create();
1643 var sinceHand = sinceFrame.hand(this.id);
1644 if(!sinceHand.valid) return vec3.create();
1645 return [
1646 this._translation[0] - sinceHand._translation[0],
1647 this._translation[1] - sinceHand._translation[1],
1648 this._translation[2] - sinceHand._translation[2]
1649 ];
1650}
1651
1652/**
1653 * A string containing a brief, human readable description of the Hand object.
1654 * @method toString
1655 * @memberof Leap.Hand.prototype
1656 * @returns {String} A description of the Hand as a string.
1657 */
1658Hand.prototype.toString = function() {
1659 return "Hand [ id: "+ this.id + " | palm velocity:"+this.palmVelocity+" | sphere center:"+this.sphereCenter+" ] ";
1660}
1661
1662/**
1663 * An invalid Hand object.
1664 *
1665 * You can use an invalid Hand object in comparisons testing
1666 * whether a given Hand instance is valid or invalid. (You can also use the
1667 * Hand valid property.)
1668 *
1669 * @static
1670 * @type {Leap.Hand}
1671 * @name Invalid
1672 * @memberof Leap.Hand
1673 */
1674Hand.Invalid = {
1675 valid: false,
1676 fingers: [],
1677 tools: [],
1678 pointables: [],
1679 pointable: function() { return Pointable.Invalid },
1680 finger: function() { return Pointable.Invalid },
1681 toString: function() { return "invalid frame" },
1682 dump: function() { return this.toString(); },
1683 rotationAngle: function() { return 0.0; },
1684 rotationMatrix: function() { return mat3.create(); },
1685 rotationAxis: function() { return vec3.create(); },
1686 scaleFactor: function() { return 1.0; },
1687 translation: function() { return vec3.create(); }
1688};
1689
1690},{"./pointable":11,"gl-matrix":19,"underscore":20}],8:[function(require,module,exports){
1691(function(){/**
1692 * Leap is the global namespace of the Leap API.
1693 * @namespace Leap
1694 */
1695module.exports = {
1696 Controller: require("./controller"),
1697 Frame: require("./frame"),
1698 Gesture: require("./gesture"),
1699 Hand: require("./hand"),
1700 Pointable: require("./pointable"),
1701 InteractionBox: require("./interaction_box"),
1702 Connection: require("./connection"),
1703 CircularBuffer: require("./circular_buffer"),
1704 UI: require("./ui"),
1705 glMatrix: require("gl-matrix"),
1706 mat3: require("gl-matrix").mat3,
1707 vec3: require("gl-matrix").vec3,
1708 loopController: undefined,
1709 /**
1710 * The Leap.loop() function passes a frame of Leap data to your
1711 * callback function and then calls window.requestAnimationFrame() after
1712 * executing your callback function.
1713 *
1714 * Leap.loop() sets up the Leap controller and WebSocket connection for you.
1715 * You do not need to create your own controller when using this method.
1716 *
1717 * Your callback function is called on an interval determined by the client
1718 * browser. Typically, this is on an interval of 60 frames/second. The most
1719 * recent frame of Leap data is passed to your callback function. If the Leap
1720 * is producing frames at a slower rate than the browser frame rate, the same
1721 * frame of Leap data can be passed to your function in successive animation
1722 * updates.
1723 *
1724 * As an alternative, you can create your own Controller object and use a
1725 * {@link Controller#onFrame onFrame} callback to process the data at
1726 * the frame rate of the Leap device. See {@link Controller} for an
1727 * example.
1728 *
1729 * @method Leap.loop
1730 * @param {function} callback A function called when the browser is ready to
1731 * draw to the screen. The most recent {@link Frame} object is passed to
1732 * your callback function.
1733 *
1734 * ```javascript
1735 * Leap.loop( function( frame ) {
1736 * // ... your code here
1737 * })
1738 * ```
1739 */
1740 loop: function(opts, callback) {
1741 if (callback === undefined) {
1742 callback = opts;
1743 opts = {};
1744 }
1745 if (!this.loopController) this.loopController = new this.Controller(opts);
1746 this.loopController.loop(callback);
1747 }
1748}
1749
1750})()
1751},{"./circular_buffer":2,"./connection":3,"./controller":4,"./frame":5,"./gesture":6,"./hand":7,"./interaction_box":9,"./pointable":11,"./ui":13,"gl-matrix":19}],9:[function(require,module,exports){
1752var glMatrix = require("gl-matrix")
1753 , vec3 = glMatrix.vec3;
1754
1755/**
1756 * Constructs a InteractionBox object.
1757 *
1758 * @class InteractionBox
1759 * @memberof Leap
1760 * @classdesc
1761 * The InteractionBox class represents a box-shaped region completely within
1762 * the field of view of the Leap Motion controller.
1763 *
1764 * The interaction box is an axis-aligned rectangular prism and provides
1765 * normalized coordinates for hands, fingers, and tools within this box.
1766 * The InteractionBox class can make it easier to map positions in the
1767 * Leap Motion coordinate system to 2D or 3D coordinate systems used
1768 * for application drawing.
1769 *
1770 * The InteractionBox region is defined by a center and dimensions along the x, y, and z axes.
1771 */
1772var InteractionBox = module.exports = function(data) {
1773 /**
1774 * Indicates whether this is a valid InteractionBox object.
1775 *
1776 * @member valid
1777 * @type {Boolean}
1778 * @memberof Leap.InteractionBox.prototype
1779 */
1780 this.valid = true;
1781 /**
1782 * The center of the InteractionBox in device coordinates (millimeters).
1783 * This point is equidistant from all sides of the box.
1784 *
1785 * @member center
1786 * @type {number[]}
1787 * @memberof Leap.InteractionBox.prototype
1788 */
1789 this.center = data.center;
1790
1791 this.size = data.size;
1792 /**
1793 * The width of the InteractionBox in millimeters, measured along the x-axis.
1794 *
1795 * @member width
1796 * @type {number}
1797 * @memberof Leap.InteractionBox.prototype
1798 */
1799 this.width = data.size[0];
1800 /**
1801 * The height of the InteractionBox in millimeters, measured along the y-axis.
1802 *
1803 * @member height
1804 * @type {number}
1805 * @memberof Leap.InteractionBox.prototype
1806 */
1807 this.height = data.size[1];
1808 /**
1809 * The depth of the InteractionBox in millimeters, measured along the z-axis.
1810 *
1811 * @member depth
1812 * @type {number}
1813 * @memberof Leap.InteractionBox.prototype
1814 */
1815 this.depth = data.size[2];
1816}
1817
1818/**
1819 * Converts a position defined by normalized InteractionBox coordinates
1820 * into device coordinates in millimeters.
1821 *
1822 * This function performs the inverse of normalizePoint().
1823 *
1824 * @method denormalizePoint
1825 * @memberof Leap.InteractionBox.prototype
1826 * @param {Leap.Vector} normalizedPosition The input position in InteractionBox coordinates.
1827 * @returns {Leap.Vector} The corresponding denormalized position in device coordinates.
1828 */
1829InteractionBox.prototype.denormalizePoint = function(normalizedPosition) {
1830 return vec3.fromValues(
1831 (normalizedPosition[0] - 0.5) * this.size[0] + this.center[0],
1832 (normalizedPosition[1] - 0.5) * this.size[1] + this.center[1],
1833 (normalizedPosition[2] - 0.5) * this.size[2] + this.center[2]
1834 );
1835}
1836
1837/**
1838 * Normalizes the coordinates of a point using the interaction box.
1839 *
1840 * Coordinates from the Leap Motion frame of reference (millimeters) are
1841 * converted to a range of [0..1] such that the minimum value of the
1842 * InteractionBox maps to 0 and the maximum value of the InteractionBox maps to 1.
1843 *
1844 * @method normalizePoint
1845 * @memberof Leap.InteractionBox.prototype
1846 * @param {Leap.Vector} position The input position in device coordinates.
1847 * @param {Boolean} clamp Whether or not to limit the output value to the range [0,1]
1848 * when the input position is outside the InteractionBox. Defaults to true.
1849 * @returns {Leap.Vector} The normalized position.
1850 */
1851InteractionBox.prototype.normalizePoint = function(position, clamp) {
1852 var vec = vec3.fromValues(
1853 ((position[0] - this.center[0]) / this.size[0]) + 0.5,
1854 ((position[1] - this.center[1]) / this.size[1]) + 0.5,
1855 ((position[2] - this.center[2]) / this.size[2]) + 0.5
1856 );
1857
1858 if (clamp) {
1859 vec[0] = Math.min(Math.max(vec[0], 0), 1);
1860 vec[1] = Math.min(Math.max(vec[1], 0), 1);
1861 vec[2] = Math.min(Math.max(vec[2], 0), 1);
1862 }
1863 return vec;
1864}
1865
1866/**
1867 * Writes a brief, human readable description of the InteractionBox object.
1868 *
1869 * @method toString
1870 * @memberof Leap.InteractionBox.prototype
1871 * @returns {String} A description of the InteractionBox object as a string.
1872 */
1873InteractionBox.prototype.toString = function() {
1874 return "InteractionBox [ width:" + this.width + " | height:" + this.height + " | depth:" + this.depth + " ]";
1875}
1876
1877/**
1878 * An invalid InteractionBox object.
1879 *
1880 * You can use this InteractionBox instance in comparisons testing
1881 * whether a given InteractionBox instance is valid or invalid. (You can also use the
1882 * InteractionBox.valid property.)
1883 *
1884 * @static
1885 * @type {Leap.InteractionBox}
1886 * @name Invalid
1887 * @memberof Leap.InteractionBox
1888 */
1889InteractionBox.Invalid = { valid: false };
1890
1891},{"gl-matrix":19}],10:[function(require,module,exports){
1892var Pipeline = module.exports = function() {
1893 this.steps = [];
1894}
1895
1896Pipeline.prototype.addStep = function(step) {
1897 this.steps.push(step);
1898}
1899
1900Pipeline.prototype.run = function(frame) {
1901 var stepsLength = this.steps.length;
1902 for (var i = 0; i != stepsLength; i++) {
1903 if (!frame) break;
1904 frame = this.steps[i](frame);
1905 }
1906 return frame;
1907}
1908
1909},{}],11:[function(require,module,exports){
1910var glMatrix = require("gl-matrix")
1911 , vec3 = glMatrix.vec3;
1912
1913/**
1914 * Constructs a Pointable object.
1915 *
1916 * An uninitialized pointable is considered invalid.
1917 * Get valid Pointable objects from a Frame or a Hand object.
1918 *
1919 * @class Pointable
1920 * @memberof Leap
1921 * @classdesc
1922 * The Pointable class reports the physical characteristics of a detected
1923 * finger or tool.
1924 *
1925 * Both fingers and tools are classified as Pointable objects. Use the
1926 * Pointable.tool property to determine whether a Pointable object represents a
1927 * tool or finger. The Leap classifies a detected entity as a tool when it is
1928 * thinner, straighter, and longer than a typical finger.
1929 *
1930 * Note that Pointable objects can be invalid, which means that they do not
1931 * contain valid tracking data and do not correspond to a physical entity.
1932 * Invalid Pointable objects can be the result of asking for a Pointable object
1933 * using an ID from an earlier frame when no Pointable objects with that ID
1934 * exist in the current frame. A Pointable object created from the Pointable
1935 * constructor is also invalid. Test for validity with the Pointable.valid
1936 * property.
1937 */
1938var Pointable = module.exports = function(data) {
1939 /**
1940 * Indicates whether this is a valid Pointable object.
1941 *
1942 * @member valid
1943 * @type {Boolean}
1944 * @memberof Leap.Pointable.prototype
1945 */
1946 this.valid = true;
1947 /**
1948 * A unique ID assigned to this Pointable object, whose value remains the
1949 * same across consecutive frames while the tracked finger or tool remains
1950 * visible. If tracking is lost (for example, when a finger is occluded by
1951 * another finger or when it is withdrawn from the Leap field of view), the
1952 * Leap may assign a new ID when it detects the entity in a future frame.
1953 *
1954 * Use the ID value with the pointable() functions defined for the
1955 * {@link Frame} and {@link Frame.Hand} classes to find this
1956 * Pointable object in future frames.
1957 *
1958 * @member id
1959 * @type {String}
1960 * @memberof Leap.Pointable.prototype
1961 */
1962 this.id = data.id;
1963 this.handId = data.handId;
1964 /**
1965 * The estimated length of the finger or tool in millimeters.
1966 *
1967 * The reported length is the visible length of the finger or tool from the
1968 * hand to tip. If the length isn't known, then a value of 0 is returned.
1969 *
1970 * @member length
1971 * @type {number}
1972 * @memberof Leap.Pointable.prototype
1973 */
1974 this.length = data.length;
1975 /**
1976 * Whether or not the Pointable is believed to be a tool.
1977 * Tools are generally longer, thinner, and straighter than fingers.
1978 *
1979 * If tool is false, then this Pointable must be a finger.
1980 *
1981 * @member tool
1982 * @type {Boolean}
1983 * @memberof Leap.Pointable.prototype
1984 */
1985 this.tool = data.tool;
1986 /**
1987 * The estimated width of the tool in millimeters.
1988 *
1989 * The reported width is the average width of the visible portion of the
1990 * tool from the hand to the tip. If the width isn't known,
1991 * then a value of 0 is returned.
1992 *
1993 * Pointable objects representing fingers do not have a width property.
1994 *
1995 * @member width
1996 * @type {number}
1997 * @memberof Leap.Pointable.prototype
1998 */
1999 this.width = data.width;
2000 /**
2001 * The direction in which this finger or tool is pointing.
2002 *
2003 * The direction is expressed as a unit vector pointing in the same
2004 * direction as the tip.
2005 *
2006 * ![Finger](images/Leap_Finger_Model.png)
2007 * @member direction
2008 * @type {number[]}
2009 * @memberof Leap.Pointable.prototype
2010 */
2011 this.direction = data.direction;
2012 /**
2013 * The tip position in millimeters from the Leap origin.
2014 * Stabilized
2015 *
2016 * @member stabilizedTipPosition
2017 * @type {Leap.Vector}
2018 * @memberof Leap.Pointable.prototype
2019 */
2020 this.stabilizedTipPosition = data.stabilizedTipPosition;
2021 /**
2022 * The tip position in millimeters from the Leap origin.
2023 *
2024 * @member tipPosition
2025 * @type {number[]}
2026 * @memberof Leap.Pointable.prototype
2027 */
2028 this.tipPosition = data.tipPosition;
2029 /**
2030 * The rate of change of the tip position in millimeters/second.
2031 *
2032 * @member tipVelocity
2033 * @type {number[]}
2034 * @memberof Leap.Pointable.prototype
2035 */
2036 this.tipVelocity = data.tipVelocity;
2037 /**
2038 * Human readable string describing the 'Touch Zone' of this pointable
2039 *
2040 * @member Pointable.prototype.touchZone {String}
2041 */
2042 this.touchZone = data.touchZone;
2043 /**
2044 * Distance from 'Touch Plane'
2045 *
2046 * @member Pointable.prototype.touchDistance {number}
2047 */
2048 this.touchDistance = data.touchDistance;
2049
2050 /**
2051 * Time the pointable has been visible in seconds.
2052 *
2053 * @member Pointable.prototype.timeVisible {float}
2054 */
2055 this.timeVisible = data.timeVisible;
2056}
2057
2058/**
2059 * A string containing a brief, human readable description of the Pointable
2060 * object.
2061 *
2062 * @method toString
2063 * @memberof Leap.Pointable.prototype
2064 * @returns {String} A description of the Pointable object as a string.
2065 */
2066Pointable.prototype.toString = function() {
2067 if(this.tool == true){
2068 return "Pointable [ id:" + this.id + " " + this.length + "mmx | with:" + this.width + "mm | direction:" + this.direction + ' ]';
2069 } else {
2070 return "Pointable [ id:" + this.id + " " + this.length + "mmx | direction: " + this.direction + ' ]';
2071 }
2072}
2073
2074/**
2075 * An invalid Pointable object.
2076 *
2077 * You can use this Pointable instance in comparisons testing
2078 * whether a given Pointable instance is valid or invalid. (You can also use the
2079 * Pointable.valid property.)
2080
2081 * @static
2082 * @type {Leap.Pointable}
2083 * @name Invalid
2084 * @memberof Leap.Pointable
2085 */
2086Pointable.Invalid = { valid: false };
2087
2088},{"gl-matrix":19}],12:[function(require,module,exports){
2089var Frame = require('./frame')
2090
2091var Event = function(data) {
2092 this.type = data.type;
2093 this.state = data.state;
2094};
2095
2096var chooseProtocol = exports.chooseProtocol = function(header) {
2097 var protocol;
2098 switch(header.version) {
2099 case 1:
2100 protocol = JSONProtocol(1, function(data) {
2101 return new Frame(data);
2102 });
2103 break;
2104 case 2:
2105 protocol = JSONProtocol(2, function(data) {
2106 return new Frame(data);
2107 });
2108 protocol.sendHeartbeat = function(connection) {
2109 connection.send(protocol.encode({heartbeat: true}));
2110 }
2111 break;
2112 case 3:
2113 protocol = JSONProtocol(3, function(data) {
2114 return data.event ? new Event(data.event) : new Frame(data);
2115
2116 });
2117 protocol.sendHeartbeat = function(connection) {
2118 connection.send(protocol.encode({heartbeat: true}));
2119 }
2120 break;
2121 default:
2122 throw "unrecognized version";
2123 }
2124 return protocol;
2125}
2126
2127var JSONProtocol = function(version, cb) {
2128 var protocol = cb;
2129 protocol.encode = function(message) {
2130 return JSON.stringify(message);
2131 }
2132 protocol.version = version;
2133 protocol.versionLong = 'Version ' + version;
2134 protocol.type = 'protocol';
2135 return protocol;
2136};
2137
2138},{"./frame":5}],13:[function(require,module,exports){
2139exports.UI = {
2140 Region: require("./ui/region"),
2141 Cursor: require("./ui/cursor")
2142};
2143},{"./ui/cursor":14,"./ui/region":15}],14:[function(require,module,exports){
2144var Cursor = module.exports = function() {
2145 return function(frame) {
2146 var pointable = frame.pointables.sort(function(a, b) { return a.z - b.z })[0]
2147 if (pointable && pointable.valid) {
2148 frame.cursorPosition = pointable.tipPosition
2149 }
2150 return frame
2151 }
2152}
2153
2154},{}],15:[function(require,module,exports){
2155var EventEmitter = require('events').EventEmitter
2156 , _ = require('underscore')
2157
2158var Region = module.exports = function(start, end) {
2159 this.start = new Vector(start)
2160 this.end = new Vector(end)
2161 this.enteredFrame = null
2162}
2163
2164Region.prototype.hasPointables = function(frame) {
2165 for (var i = 0; i != frame.pointables.length; i++) {
2166 var position = frame.pointables[i].tipPosition
2167 if (position.x >= this.start.x && position.x <= this.end.x && position.y >= this.start.y && position.y <= this.end.y && position.z >= this.start.z && position.z <= this.end.z) {
2168 return true
2169 }
2170 }
2171 return false
2172}
2173
2174Region.prototype.listener = function(opts) {
2175 var region = this
2176 if (opts && opts.nearThreshold) this.setupNearRegion(opts.nearThreshold)
2177 return function(frame) {
2178 return region.updatePosition(frame)
2179 }
2180}
2181
2182Region.prototype.clipper = function() {
2183 var region = this
2184 return function(frame) {
2185 region.updatePosition(frame)
2186 return region.enteredFrame ? frame : null
2187 }
2188}
2189
2190Region.prototype.setupNearRegion = function(distance) {
2191 var nearRegion = this.nearRegion = new Region(
2192 [this.start.x - distance, this.start.y - distance, this.start.z - distance],
2193 [this.end.x + distance, this.end.y + distance, this.end.z + distance]
2194 )
2195 var region = this
2196 nearRegion.on("enter", function(frame) {
2197 region.emit("near", frame)
2198 })
2199 nearRegion.on("exit", function(frame) {
2200 region.emit("far", frame)
2201 })
2202 region.on('exit', function(frame) {
2203 region.emit("near", frame)
2204 })
2205}
2206
2207Region.prototype.updatePosition = function(frame) {
2208 if (this.nearRegion) this.nearRegion.updatePosition(frame)
2209 if (this.hasPointables(frame) && this.enteredFrame == null) {
2210 this.enteredFrame = frame
2211 this.emit("enter", this.enteredFrame)
2212 } else if (!this.hasPointables(frame) && this.enteredFrame != null) {
2213 this.enteredFrame = null
2214 this.emit("exit", this.enteredFrame)
2215 }
2216 return frame
2217}
2218
2219Region.prototype.normalize = function(position) {
2220 return new Vector([
2221 (position.x - this.start.x) / (this.end.x - this.start.x),
2222 (position.y - this.start.y) / (this.end.y - this.start.y),
2223 (position.z - this.start.z) / (this.end.z - this.start.z)
2224 ])
2225}
2226
2227Region.prototype.mapToXY = function(position, width, height) {
2228 var normalized = this.normalize(position)
2229 var x = normalized.x, y = normalized.y
2230 if (x > 1) x = 1
2231 else if (x < -1) x = -1
2232 if (y > 1) y = 1
2233 else if (y < -1) y = -1
2234 return [
2235 (x + 1) / 2 * width,
2236 (1 - y) / 2 * height,
2237 normalized.z
2238 ]
2239}
2240
2241_.extend(Region.prototype, EventEmitter.prototype)
2242},{"events":17,"underscore":20}],16:[function(require,module,exports){
2243
2244},{}],17:[function(require,module,exports){
2245(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
2246
2247var EventEmitter = exports.EventEmitter = process.EventEmitter;
2248var isArray = typeof Array.isArray === 'function'
2249 ? Array.isArray
2250 : function (xs) {
2251 return Object.prototype.toString.call(xs) === '[object Array]'
2252 }
2253;
2254function indexOf (xs, x) {
2255 if (xs.indexOf) return xs.indexOf(x);
2256 for (var i = 0; i < xs.length; i++) {
2257 if (x === xs[i]) return i;
2258 }
2259 return -1;
2260}
2261
2262// By default EventEmitters will print a warning if more than
2263// 10 listeners are added to it. This is a useful default which
2264// helps finding memory leaks.
2265//
2266// Obviously not all Emitters should be limited to 10. This function allows
2267// that to be increased. Set to zero for unlimited.
2268var defaultMaxListeners = 10;
2269EventEmitter.prototype.setMaxListeners = function(n) {
2270 if (!this._events) this._events = {};
2271 this._events.maxListeners = n;
2272};
2273
2274
2275EventEmitter.prototype.emit = function(type) {
2276 // If there is no 'error' event listener then throw.
2277 if (type === 'error') {
2278 if (!this._events || !this._events.error ||
2279 (isArray(this._events.error) && !this._events.error.length))
2280 {
2281 if (arguments[1] instanceof Error) {
2282 throw arguments[1]; // Unhandled 'error' event
2283 } else {
2284 throw new Error("Uncaught, unspecified 'error' event.");
2285 }
2286 return false;
2287 }
2288 }
2289
2290 if (!this._events) return false;
2291 var handler = this._events[type];
2292 if (!handler) return false;
2293
2294 if (typeof handler == 'function') {
2295 switch (arguments.length) {
2296 // fast cases
2297 case 1:
2298 handler.call(this);
2299 break;
2300 case 2:
2301 handler.call(this, arguments[1]);
2302 break;
2303 case 3:
2304 handler.call(this, arguments[1], arguments[2]);
2305 break;
2306 // slower
2307 default:
2308 var args = Array.prototype.slice.call(arguments, 1);
2309 handler.apply(this, args);
2310 }
2311 return true;
2312
2313 } else if (isArray(handler)) {
2314 var args = Array.prototype.slice.call(arguments, 1);
2315
2316 var listeners = handler.slice();
2317 for (var i = 0, l = listeners.length; i < l; i++) {
2318 listeners[i].apply(this, args);
2319 }
2320 return true;
2321
2322 } else {
2323 return false;
2324 }
2325};
2326
2327// EventEmitter is defined in src/node_events.cc
2328// EventEmitter.prototype.emit() is also defined there.
2329EventEmitter.prototype.addListener = function(type, listener) {
2330 if ('function' !== typeof listener) {
2331 throw new Error('addListener only takes instances of Function');
2332 }
2333
2334 if (!this._events) this._events = {};
2335
2336 // To avoid recursion in the case that type == "newListeners"! Before
2337 // adding it to the listeners, first emit "newListeners".
2338 this.emit('newListener', type, listener);
2339
2340 if (!this._events[type]) {
2341 // Optimize the case of one listener. Don't need the extra array object.
2342 this._events[type] = listener;
2343 } else if (isArray(this._events[type])) {
2344
2345 // Check for listener leak
2346 if (!this._events[type].warned) {
2347 var m;
2348 if (this._events.maxListeners !== undefined) {
2349 m = this._events.maxListeners;
2350 } else {
2351 m = defaultMaxListeners;
2352 }
2353
2354 if (m && m > 0 && this._events[type].length > m) {
2355 this._events[type].warned = true;
2356 console.error('(node) warning: possible EventEmitter memory ' +
2357 'leak detected. %d listeners added. ' +
2358 'Use emitter.setMaxListeners() to increase limit.',
2359 this._events[type].length);
2360 console.trace();
2361 }
2362 }
2363
2364 // If we've already got an array, just append.
2365 this._events[type].push(listener);
2366 } else {
2367 // Adding the second element, need to change to array.
2368 this._events[type] = [this._events[type], listener];
2369 }
2370
2371 return this;
2372};
2373
2374EventEmitter.prototype.on = EventEmitter.prototype.addListener;
2375
2376EventEmitter.prototype.once = function(type, listener) {
2377 var self = this;
2378 self.on(type, function g() {
2379 self.removeListener(type, g);
2380 listener.apply(this, arguments);
2381 });
2382
2383 return this;
2384};
2385
2386EventEmitter.prototype.removeListener = function(type, listener) {
2387 if ('function' !== typeof listener) {
2388 throw new Error('removeListener only takes instances of Function');
2389 }
2390
2391 // does not use listeners(), so no side effect of creating _events[type]
2392 if (!this._events || !this._events[type]) return this;
2393
2394 var list = this._events[type];
2395
2396 if (isArray(list)) {
2397 var i = indexOf(list, listener);
2398 if (i < 0) return this;
2399 list.splice(i, 1);
2400 if (list.length == 0)
2401 delete this._events[type];
2402 } else if (this._events[type] === listener) {
2403 delete this._events[type];
2404 }
2405
2406 return this;
2407};
2408
2409EventEmitter.prototype.removeAllListeners = function(type) {
2410 if (arguments.length === 0) {
2411 this._events = {};
2412 return this;
2413 }
2414
2415 // does not use listeners(), so no side effect of creating _events[type]
2416 if (type && this._events && this._events[type]) this._events[type] = null;
2417 return this;
2418};
2419
2420EventEmitter.prototype.listeners = function(type) {
2421 if (!this._events) this._events = {};
2422 if (!this._events[type]) this._events[type] = [];
2423 if (!isArray(this._events[type])) {
2424 this._events[type] = [this._events[type]];
2425 }
2426 return this._events[type];
2427};
2428
2429})(require("__browserify_process"))
2430},{"__browserify_process":18}],18:[function(require,module,exports){
2431// shim for using process in browser
2432
2433var process = module.exports = {};
2434
2435process.nextTick = (function () {
2436 var canSetImmediate = typeof window !== 'undefined'
2437 && window.setImmediate;
2438 var canPost = typeof window !== 'undefined'
2439 && window.postMessage && window.addEventListener
2440 ;
2441
2442 if (canSetImmediate) {
2443 return function (f) { return window.setImmediate(f) };
2444 }
2445
2446 if (canPost) {
2447 var queue = [];
2448 window.addEventListener('message', function (ev) {
2449 if (ev.source === window && ev.data === 'process-tick') {
2450 ev.stopPropagation();
2451 if (queue.length > 0) {
2452 var fn = queue.shift();
2453 fn();
2454 }
2455 }
2456 }, true);
2457
2458 return function nextTick(fn) {
2459 queue.push(fn);
2460 window.postMessage('process-tick', '*');
2461 };
2462 }
2463
2464 return function nextTick(fn) {
2465 setTimeout(fn, 0);
2466 };
2467})();
2468
2469process.title = 'browser';
2470process.browser = true;
2471process.env = {};
2472process.argv = [];
2473
2474process.binding = function (name) {
2475 throw new Error('process.binding is not supported');
2476}
2477
2478// TODO(shtylman)
2479process.cwd = function () { return '/' };
2480process.chdir = function (dir) {
2481 throw new Error('process.chdir is not supported');
2482};
2483
2484},{}],19:[function(require,module,exports){
2485(function(){/**
2486 * @fileoverview gl-matrix - High performance matrix and vector operations
2487 * @author Brandon Jones
2488 * @author Colin MacKenzie IV
2489 * @version 2.0.0
2490 */
2491
2492/* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
2493
2494Redistribution and use in source and binary forms, with or without modification,
2495are permitted provided that the following conditions are met:
2496
2497 * Redistributions of source code must retain the above copyright notice, this
2498 list of conditions and the following disclaimer.
2499 * Redistributions in binary form must reproduce the above copyright notice,
2500 this list of conditions and the following disclaimer in the documentation
2501 and/or other materials provided with the distribution.
2502
2503THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2504ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2505WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2506DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
2507ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2508(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2509LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2510ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2512SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
2513
2514
2515(function() {
2516 "use strict";
2517
2518 var shim = {};
2519 if (typeof(exports) === 'undefined') {
2520 if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
2521 shim.exports = {};
2522 define(function() {
2523 return shim.exports;
2524 });
2525 } else {
2526 // gl-matrix lives in a browser, define its namespaces in global
2527 shim.exports = window;
2528 }
2529 }
2530 else {
2531 // gl-matrix lives in commonjs, define its namespaces in exports
2532 shim.exports = exports;
2533 }
2534
2535 (function(exports) {
2536 /* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
2537
2538Redistribution and use in source and binary forms, with or without modification,
2539are permitted provided that the following conditions are met:
2540
2541 * Redistributions of source code must retain the above copyright notice, this
2542 list of conditions and the following disclaimer.
2543 * Redistributions in binary form must reproduce the above copyright notice,
2544 this list of conditions and the following disclaimer in the documentation
2545 and/or other materials provided with the distribution.
2546
2547THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2548ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2549WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2550DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
2551ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2552(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2553LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2554ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2555(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2556SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
2557
2558/**
2559 * @class 2 Dimensional Vector
2560 * @name vec2
2561 */
2562
2563var vec2 = {};
2564
2565if(!GLMAT_EPSILON) {
2566 var GLMAT_EPSILON = 0.000001;
2567}
2568
2569/**
2570 * Creates a new, empty vec2
2571 *
2572 * @returns {vec2} a new 2D vector
2573 */
2574vec2.create = function() {
2575 return new Float32Array(2);
2576};
2577
2578/**
2579 * Creates a new vec2 initialized with values from an existing vector
2580 *
2581 * @param {vec2} a vector to clone
2582 * @returns {vec2} a new 2D vector
2583 */
2584vec2.clone = function(a) {
2585 var out = new Float32Array(2);
2586 out[0] = a[0];
2587 out[1] = a[1];
2588 return out;
2589};
2590
2591/**
2592 * Creates a new vec2 initialized with the given values
2593 *
2594 * @param {Number} x X component
2595 * @param {Number} y Y component
2596 * @returns {vec2} a new 2D vector
2597 */
2598vec2.fromValues = function(x, y) {
2599 var out = new Float32Array(2);
2600 out[0] = x;
2601 out[1] = y;
2602 return out;
2603};
2604
2605/**
2606 * Copy the values from one vec2 to another
2607 *
2608 * @param {vec2} out the receiving vector
2609 * @param {vec2} a the source vector
2610 * @returns {vec2} out
2611 */
2612vec2.copy = function(out, a) {
2613 out[0] = a[0];
2614 out[1] = a[1];
2615 return out;
2616};
2617
2618/**
2619 * Set the components of a vec2 to the given values
2620 *
2621 * @param {vec2} out the receiving vector
2622 * @param {Number} x X component
2623 * @param {Number} y Y component
2624 * @returns {vec2} out
2625 */
2626vec2.set = function(out, x, y) {
2627 out[0] = x;
2628 out[1] = y;
2629 return out;
2630};
2631
2632/**
2633 * Adds two vec2's
2634 *
2635 * @param {vec2} out the receiving vector
2636 * @param {vec2} a the first operand
2637 * @param {vec2} b the second operand
2638 * @returns {vec2} out
2639 */
2640vec2.add = function(out, a, b) {
2641 out[0] = a[0] + b[0];
2642 out[1] = a[1] + b[1];
2643 return out;
2644};
2645
2646/**
2647 * Subtracts two vec2's
2648 *
2649 * @param {vec2} out the receiving vector
2650 * @param {vec2} a the first operand
2651 * @param {vec2} b the second operand
2652 * @returns {vec2} out
2653 */
2654vec2.sub = vec2.subtract = function(out, a, b) {
2655 out[0] = a[0] - b[0];
2656 out[1] = a[1] - b[1];
2657 return out;
2658};
2659
2660/**
2661 * Multiplies two vec2's
2662 *
2663 * @param {vec2} out the receiving vector
2664 * @param {vec2} a the first operand
2665 * @param {vec2} b the second operand
2666 * @returns {vec2} out
2667 */
2668vec2.mul = vec2.multiply = function(out, a, b) {
2669 out[0] = a[0] * b[0];
2670 out[1] = a[1] * b[1];
2671 return out;
2672};
2673
2674/**
2675 * Divides two vec2's
2676 *
2677 * @param {vec2} out the receiving vector
2678 * @param {vec2} a the first operand
2679 * @param {vec2} b the second operand
2680 * @returns {vec2} out
2681 */
2682vec2.div = vec2.divide = function(out, a, b) {
2683 out[0] = a[0] / b[0];
2684 out[1] = a[1] / b[1];
2685 return out;
2686};
2687
2688/**
2689 * Returns the minimum of two vec2's
2690 *
2691 * @param {vec2} out the receiving vector
2692 * @param {vec2} a the first operand
2693 * @param {vec2} b the second operand
2694 * @returns {vec2} out
2695 */
2696vec2.min = function(out, a, b) {
2697 out[0] = Math.min(a[0], b[0]);
2698 out[1] = Math.min(a[1], b[1]);
2699 return out;
2700};
2701
2702/**
2703 * Returns the maximum of two vec2's
2704 *
2705 * @param {vec2} out the receiving vector
2706 * @param {vec2} a the first operand
2707 * @param {vec2} b the second operand
2708 * @returns {vec2} out
2709 */
2710vec2.max = function(out, a, b) {
2711 out[0] = Math.max(a[0], b[0]);
2712 out[1] = Math.max(a[1], b[1]);
2713 return out;
2714};
2715
2716/**
2717 * Scales a vec2 by a scalar number
2718 *
2719 * @param {vec2} out the receiving vector
2720 * @param {vec2} a the vector to scale
2721 * @param {vec2} b amount to scale the vector by
2722 * @returns {vec2} out
2723 */
2724vec2.scale = function(out, a, b) {
2725 out[0] = a[0] * b;
2726 out[1] = a[1] * b;
2727 return out;
2728};
2729
2730/**
2731 * Calculates the euclidian distance between two vec2's
2732 *
2733 * @param {vec2} a the first operand
2734 * @param {vec2} b the second operand
2735 * @returns {Number} distance between a and b
2736 */
2737vec2.dist = vec2.distance = function(a, b) {
2738 var x = b[0] - a[0],
2739 y = b[1] - a[1];
2740 return Math.sqrt(x*x + y*y);
2741};
2742
2743/**
2744 * Calculates the squared euclidian distance between two vec2's
2745 *
2746 * @param {vec2} a the first operand
2747 * @param {vec2} b the second operand
2748 * @returns {Number} squared distance between a and b
2749 */
2750vec2.sqrDist = vec2.squaredDistance = function(a, b) {
2751 var x = b[0] - a[0],
2752 y = b[1] - a[1];
2753 return x*x + y*y;
2754};
2755
2756/**
2757 * Caclulates the length of a vec2
2758 *
2759 * @param {vec2} a vector to calculate length of
2760 * @returns {Number} length of a
2761 */
2762vec2.len = vec2.length = function (a) {
2763 var x = a[0],
2764 y = a[1];
2765 return Math.sqrt(x*x + y*y);
2766};
2767
2768/**
2769 * Caclulates the squared length of a vec2
2770 *
2771 * @param {vec2} a vector to calculate squared length of
2772 * @returns {Number} squared length of a
2773 */
2774vec2.sqrLen = vec2.squaredLength = function (a) {
2775 var x = a[0],
2776 y = a[1];
2777 return x*x + y*y;
2778};
2779
2780/**
2781 * Negates the components of a vec2
2782 *
2783 * @param {vec2} out the receiving vector
2784 * @param {vec2} a vector to negate
2785 * @returns {vec2} out
2786 */
2787vec2.negate = function(out, a) {
2788 out[0] = -a[0];
2789 out[1] = -a[1];
2790 return out;
2791};
2792
2793/**
2794 * Normalize a vec2
2795 *
2796 * @param {vec2} out the receiving vector
2797 * @param {vec2} a vector to normalize
2798 * @returns {vec2} out
2799 */
2800vec2.normalize = function(out, a) {
2801 var x = a[0],
2802 y = a[1];
2803 var len = x*x + y*y;
2804 if (len > 0) {
2805 //TODO: evaluate use of glm_invsqrt here?
2806 len = 1 / Math.sqrt(len);
2807 out[0] = a[0] * len;
2808 out[1] = a[1] * len;
2809 }
2810 return out;
2811};
2812
2813/**
2814 * Caclulates the dot product of two vec2's
2815 *
2816 * @param {vec2} a the first operand
2817 * @param {vec2} b the second operand
2818 * @returns {Number} dot product of a and b
2819 */
2820vec2.dot = function (a, b) {
2821 return a[0] * b[0] + a[1] * b[1];
2822};
2823
2824/**
2825 * Computes the cross product of two vec2's
2826 * Note that the cross product must by definition produce a 3D vector
2827 *
2828 * @param {vec3} out the receiving vector
2829 * @param {vec2} a the first operand
2830 * @param {vec2} b the second operand
2831 * @returns {vec3} out
2832 */
2833vec2.cross = function(out, a, b) {
2834 var z = a[0] * b[1] - a[1] * b[0];
2835 out[0] = out[1] = 0;
2836 out[2] = z;
2837 return out;
2838};
2839
2840/**
2841 * Performs a linear interpolation between two vec2's
2842 *
2843 * @param {vec3} out the receiving vector
2844 * @param {vec2} a the first operand
2845 * @param {vec2} b the second operand
2846 * @param {Number} t interpolation amount between the two inputs
2847 * @returns {vec2} out
2848 */
2849vec2.lerp = function (out, a, b, t) {
2850 var ax = a[0],
2851 ay = a[1];
2852 out[0] = ax + t * (b[0] - ax);
2853 out[1] = ay + t * (b[1] - ay);
2854 return out;
2855};
2856
2857/**
2858 * Transforms the vec2 with a mat2
2859 *
2860 * @param {vec2} out the receiving vector
2861 * @param {vec2} a the vector to transform
2862 * @param {mat2} m matrix to transform with
2863 * @returns {vec2} out
2864 */
2865vec2.transformMat2 = function(out, a, m) {
2866 var x = a[0],
2867 y = a[1];
2868 out[0] = x * m[0] + y * m[1];
2869 out[1] = x * m[2] + y * m[3];
2870 return out;
2871};
2872
2873/**
2874 * Perform some operation over an array of vec2s.
2875 *
2876 * @param {Array} a the array of vectors to iterate over
2877 * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
2878 * @param {Number} offset Number of elements to skip at the beginning of the array
2879 * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
2880 * @param {Function} fn Function to call for each vector in the array
2881 * @param {Object} [arg] additional argument to pass to fn
2882 * @returns {Array} a
2883 */
2884vec2.forEach = (function() {
2885 var vec = new Float32Array(2);
2886
2887 return function(a, stride, offset, count, fn, arg) {
2888 var i, l;
2889 if(!stride) {
2890 stride = 2;
2891 }
2892
2893 if(!offset) {
2894 offset = 0;
2895 }
2896
2897 if(count) {
2898 l = Math.min((count * stride) + offset, a.length);
2899 } else {
2900 l = a.length;
2901 }
2902
2903 for(i = offset; i < l; i += stride) {
2904 vec[0] = a[i]; vec[1] = a[i+1];
2905 fn(vec, vec, arg);
2906 a[i] = vec[0]; a[i+1] = vec[1];
2907 }
2908
2909 return a;
2910 };
2911})();
2912
2913/**
2914 * Returns a string representation of a vector
2915 *
2916 * @param {vec2} vec vector to represent as a string
2917 * @returns {String} string representation of the vector
2918 */
2919vec2.str = function (a) {
2920 return 'vec2(' + a[0] + ', ' + a[1] + ')';
2921};
2922
2923if(typeof(exports) !== 'undefined') {
2924 exports.vec2 = vec2;
2925}
2926;
2927/* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
2928
2929Redistribution and use in source and binary forms, with or without modification,
2930are permitted provided that the following conditions are met:
2931
2932 * Redistributions of source code must retain the above copyright notice, this
2933 list of conditions and the following disclaimer.
2934 * Redistributions in binary form must reproduce the above copyright notice,
2935 this list of conditions and the following disclaimer in the documentation
2936 and/or other materials provided with the distribution.
2937
2938THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2939ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2940WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2941DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
2942ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2943(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2944LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2945ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2946(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2947SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
2948
2949/**
2950 * @class 3 Dimensional Vector
2951 * @name vec3
2952 */
2953
2954var vec3 = {};
2955
2956if(!GLMAT_EPSILON) {
2957 var GLMAT_EPSILON = 0.000001;
2958}
2959
2960/**
2961 * Creates a new, empty vec3
2962 *
2963 * @returns {vec3} a new 3D vector
2964 */
2965vec3.create = function() {
2966 return new Float32Array(3);
2967};
2968
2969/**
2970 * Creates a new vec3 initialized with values from an existing vector
2971 *
2972 * @param {vec3} a vector to clone
2973 * @returns {vec3} a new 3D vector
2974 */
2975vec3.clone = function(a) {
2976 var out = new Float32Array(3);
2977 out[0] = a[0];
2978 out[1] = a[1];
2979 out[2] = a[2];
2980 return out;
2981};
2982
2983/**
2984 * Creates a new vec3 initialized with the given values
2985 *
2986 * @param {Number} x X component
2987 * @param {Number} y Y component
2988 * @param {Number} z Z component
2989 * @returns {vec3} a new 3D vector
2990 */
2991vec3.fromValues = function(x, y, z) {
2992 var out = new Float32Array(3);
2993 out[0] = x;
2994 out[1] = y;
2995 out[2] = z;
2996 return out;
2997};
2998
2999/**
3000 * Copy the values from one vec3 to another
3001 *
3002 * @param {vec3} out the receiving vector
3003 * @param {vec3} a the source vector
3004 * @returns {vec3} out
3005 */
3006vec3.copy = function(out, a) {
3007 out[0] = a[0];
3008 out[1] = a[1];
3009 out[2] = a[2];
3010 return out;
3011};
3012
3013/**
3014 * Set the components of a vec3 to the given values
3015 *
3016 * @param {vec3} out the receiving vector
3017 * @param {Number} x X component
3018 * @param {Number} y Y component
3019 * @param {Number} z Z component
3020 * @returns {vec3} out
3021 */
3022vec3.set = function(out, x, y, z) {
3023 out[0] = x;
3024 out[1] = y;
3025 out[2] = z;
3026 return out;
3027};
3028
3029/**
3030 * Adds two vec3's
3031 *
3032 * @param {vec3} out the receiving vector
3033 * @param {vec3} a the first operand
3034 * @param {vec3} b the second operand
3035 * @returns {vec3} out
3036 */
3037vec3.add = function(out, a, b) {
3038 out[0] = a[0] + b[0];
3039 out[1] = a[1] + b[1];
3040 out[2] = a[2] + b[2];
3041 return out;
3042};
3043
3044/**
3045 * Subtracts two vec3's
3046 *
3047 * @param {vec3} out the receiving vector
3048 * @param {vec3} a the first operand
3049 * @param {vec3} b the second operand
3050 * @returns {vec3} out
3051 */
3052vec3.sub = vec3.subtract = function(out, a, b) {
3053 out[0] = a[0] - b[0];
3054 out[1] = a[1] - b[1];
3055 out[2] = a[2] - b[2];
3056 return out;
3057};
3058
3059/**
3060 * Multiplies two vec3's
3061 *
3062 * @param {vec3} out the receiving vector
3063 * @param {vec3} a the first operand
3064 * @param {vec3} b the second operand
3065 * @returns {vec3} out
3066 */
3067vec3.mul = vec3.multiply = function(out, a, b) {
3068 out[0] = a[0] * b[0];
3069 out[1] = a[1] * b[1];
3070 out[2] = a[2] * b[2];
3071 return out;
3072};
3073
3074/**
3075 * Divides two vec3's
3076 *
3077 * @param {vec3} out the receiving vector
3078 * @param {vec3} a the first operand
3079 * @param {vec3} b the second operand
3080 * @returns {vec3} out
3081 */
3082vec3.div = vec3.divide = function(out, a, b) {
3083 out[0] = a[0] / b[0];
3084 out[1] = a[1] / b[1];
3085 out[2] = a[2] / b[2];
3086 return out;
3087};
3088
3089/**
3090 * Returns the minimum of two vec3's
3091 *
3092 * @param {vec3} out the receiving vector
3093 * @param {vec3} a the first operand
3094 * @param {vec3} b the second operand
3095 * @returns {vec3} out
3096 */
3097vec3.min = function(out, a, b) {
3098 out[0] = Math.min(a[0], b[0]);
3099 out[1] = Math.min(a[1], b[1]);
3100 out[2] = Math.min(a[2], b[2]);
3101 return out;
3102};
3103
3104/**
3105 * Returns the maximum of two vec3's
3106 *
3107 * @param {vec3} out the receiving vector
3108 * @param {vec3} a the first operand
3109 * @param {vec3} b the second operand
3110 * @returns {vec3} out
3111 */
3112vec3.max = function(out, a, b) {
3113 out[0] = Math.max(a[0], b[0]);
3114 out[1] = Math.max(a[1], b[1]);
3115 out[2] = Math.max(a[2], b[2]);
3116 return out;
3117};
3118
3119/**
3120 * Scales a vec3 by a scalar number
3121 *
3122 * @param {vec3} out the receiving vector
3123 * @param {vec3} a the vector to scale
3124 * @param {vec3} b amount to scale the vector by
3125 * @returns {vec3} out
3126 */
3127vec3.scale = function(out, a, b) {
3128 out[0] = a[0] * b;
3129 out[1] = a[1] * b;
3130 out[2] = a[2] * b;
3131 return out;
3132};
3133
3134/**
3135 * Calculates the euclidian distance between two vec3's
3136 *
3137 * @param {vec3} a the first operand
3138 * @param {vec3} b the second operand
3139 * @returns {Number} distance between a and b
3140 */
3141vec3.dist = vec3.distance = function(a, b) {
3142 var x = b[0] - a[0],
3143 y = b[1] - a[1],
3144 z = b[2] - a[2];
3145 return Math.sqrt(x*x + y*y + z*z);
3146};
3147
3148/**
3149 * Calculates the squared euclidian distance between two vec3's
3150 *
3151 * @param {vec3} a the first operand
3152 * @param {vec3} b the second operand
3153 * @returns {Number} squared distance between a and b
3154 */
3155vec3.sqrDist = vec3.squaredDistance = function(a, b) {
3156 var x = b[0] - a[0],
3157 y = b[1] - a[1],
3158 z = b[2] - a[2];
3159 return x*x + y*y + z*z;
3160};
3161
3162/**
3163 * Caclulates the length of a vec3
3164 *
3165 * @param {vec3} a vector to calculate length of
3166 * @returns {Number} length of a
3167 */
3168vec3.len = vec3.length = function (a) {
3169 var x = a[0],
3170 y = a[1],
3171 z = a[2];
3172 return Math.sqrt(x*x + y*y + z*z);
3173};
3174
3175/**
3176 * Caclulates the squared length of a vec3
3177 *
3178 * @param {vec3} a vector to calculate squared length of
3179 * @returns {Number} squared length of a
3180 */
3181vec3.sqrLen = vec3.squaredLength = function (a) {
3182 var x = a[0],
3183 y = a[1],
3184 z = a[2];
3185 return x*x + y*y + z*z;
3186};
3187
3188/**
3189 * Negates the components of a vec3
3190 *
3191 * @param {vec3} out the receiving vector
3192 * @param {vec3} a vector to negate
3193 * @returns {vec3} out
3194 */
3195vec3.negate = function(out, a) {
3196 out[0] = -a[0];
3197 out[1] = -a[1];
3198 out[2] = -a[2];
3199 return out;
3200};
3201
3202/**
3203 * Normalize a vec3
3204 *
3205 * @param {vec3} out the receiving vector
3206 * @param {vec3} a vector to normalize
3207 * @returns {vec3} out
3208 */
3209vec3.normalize = function(out, a) {
3210 var x = a[0],
3211 y = a[1],
3212 z = a[2];
3213 var len = x*x + y*y + z*z;
3214 if (len > 0) {
3215 //TODO: evaluate use of glm_invsqrt here?
3216 len = 1 / Math.sqrt(len);
3217 out[0] = a[0] * len;
3218 out[1] = a[1] * len;
3219 out[2] = a[2] * len;
3220 }
3221 return out;
3222};
3223
3224/**
3225 * Caclulates the dot product of two vec3's
3226 *
3227 * @param {vec3} a the first operand
3228 * @param {vec3} b the second operand
3229 * @returns {Number} dot product of a and b
3230 */
3231vec3.dot = function (a, b) {
3232 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
3233};
3234
3235/**
3236 * Computes the cross product of two vec3's
3237 *
3238 * @param {vec3} out the receiving vector
3239 * @param {vec3} a the first operand
3240 * @param {vec3} b the second operand
3241 * @returns {vec3} out
3242 */
3243vec3.cross = function(out, a, b) {
3244 var ax = a[0], ay = a[1], az = a[2],
3245 bx = b[0], by = b[1], bz = b[2];
3246
3247 out[0] = ay * bz - az * by;
3248 out[1] = az * bx - ax * bz;
3249 out[2] = ax * by - ay * bx;
3250 return out;
3251};
3252
3253/**
3254 * Performs a linear interpolation between two vec3's
3255 *
3256 * @param {vec3} out the receiving vector
3257 * @param {vec3} a the first operand
3258 * @param {vec3} b the second operand
3259 * @param {Number} t interpolation amount between the two inputs
3260 * @returns {vec3} out
3261 */
3262vec3.lerp = function (out, a, b, t) {
3263 var ax = a[0],
3264 ay = a[1],
3265 az = a[2];
3266 out[0] = ax + t * (b[0] - ax);
3267 out[1] = ay + t * (b[1] - ay);
3268 out[2] = az + t * (b[2] - az);
3269 return out;
3270};
3271
3272/**
3273 * Transforms the vec3 with a mat4.
3274 * 4th vector component is implicitly '1'
3275 *
3276 * @param {vec3} out the receiving vector
3277 * @param {vec3} a the vector to transform
3278 * @param {mat4} m matrix to transform with
3279 * @returns {vec3} out
3280 */
3281vec3.transformMat4 = function(out, a, m) {
3282 var x = a[0], y = a[1], z = a[2];
3283 out[0] = m[0] * x + m[4] * y + m[8] * z + m[12];
3284 out[1] = m[1] * x + m[5] * y + m[9] * z + m[13];
3285 out[2] = m[2] * x + m[6] * y + m[10] * z + m[14];
3286 return out;
3287};
3288
3289/**
3290 * Transforms the vec3 with a quat
3291 *
3292 * @param {vec3} out the receiving vector
3293 * @param {vec3} a the vector to transform
3294 * @param {quat} q quaternion to transform with
3295 * @returns {vec3} out
3296 */
3297vec3.transformQuat = function(out, a, q) {
3298 var x = a[0], y = a[1], z = a[2],
3299 qx = q[0], qy = q[1], qz = q[2], qw = q[3],
3300
3301 // calculate quat * vec
3302 ix = qw * x + qy * z - qz * y,
3303 iy = qw * y + qz * x - qx * z,
3304 iz = qw * z + qx * y - qy * x,
3305 iw = -qx * x - qy * y - qz * z;
3306
3307 // calculate result * inverse quat
3308 out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
3309 out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
3310 out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
3311 return out;
3312};
3313
3314/**
3315 * Perform some operation over an array of vec3s.
3316 *
3317 * @param {Array} a the array of vectors to iterate over
3318 * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
3319 * @param {Number} offset Number of elements to skip at the beginning of the array
3320 * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
3321 * @param {Function} fn Function to call for each vector in the array
3322 * @param {Object} [arg] additional argument to pass to fn
3323 * @returns {Array} a
3324 */
3325vec3.forEach = (function() {
3326 var vec = new Float32Array(3);
3327
3328 return function(a, stride, offset, count, fn, arg) {
3329 var i, l;
3330 if(!stride) {
3331 stride = 3;
3332 }
3333
3334 if(!offset) {
3335 offset = 0;
3336 }
3337
3338 if(count) {
3339 l = Math.min((count * stride) + offset, a.length);
3340 } else {
3341 l = a.length;
3342 }
3343
3344 for(i = offset; i < l; i += stride) {
3345 vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
3346 fn(vec, vec, arg);
3347 a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
3348 }
3349
3350 return a;
3351 };
3352})();
3353
3354/**
3355 * Returns a string representation of a vector
3356 *
3357 * @param {vec3} vec vector to represent as a string
3358 * @returns {String} string representation of the vector
3359 */
3360vec3.str = function (a) {
3361 return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
3362};
3363
3364if(typeof(exports) !== 'undefined') {
3365 exports.vec3 = vec3;
3366}
3367;
3368/* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
3369
3370Redistribution and use in source and binary forms, with or without modification,
3371are permitted provided that the following conditions are met:
3372
3373 * Redistributions of source code must retain the above copyright notice, this
3374 list of conditions and the following disclaimer.
3375 * Redistributions in binary form must reproduce the above copyright notice,
3376 this list of conditions and the following disclaimer in the documentation
3377 and/or other materials provided with the distribution.
3378
3379THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
3380ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3381WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3382DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
3383ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3384(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3385LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3386ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3387(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3388SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
3389
3390/**
3391 * @class 4 Dimensional Vector
3392 * @name vec4
3393 */
3394
3395var vec4 = {};
3396
3397if(!GLMAT_EPSILON) {
3398 var GLMAT_EPSILON = 0.000001;
3399}
3400
3401/**
3402 * Creates a new, empty vec4
3403 *
3404 * @returns {vec4} a new 4D vector
3405 */
3406vec4.create = function() {
3407 return new Float32Array(4);
3408};
3409
3410/**
3411 * Creates a new vec4 initialized with values from an existing vector
3412 *
3413 * @param {vec4} a vector to clone
3414 * @returns {vec4} a new 4D vector
3415 */
3416vec4.clone = function(a) {
3417 var out = new Float32Array(4);
3418 out[0] = a[0];
3419 out[1] = a[1];
3420 out[2] = a[2];
3421 out[3] = a[3];
3422 return out;
3423};
3424
3425/**
3426 * Creates a new vec4 initialized with the given values
3427 *
3428 * @param {Number} x X component
3429 * @param {Number} y Y component
3430 * @param {Number} z Z component
3431 * @param {Number} w W component
3432 * @returns {vec4} a new 4D vector
3433 */
3434vec4.fromValues = function(x, y, z, w) {
3435 var out = new Float32Array(4);
3436 out[0] = x;
3437 out[1] = y;
3438 out[2] = z;
3439 out[3] = w;
3440 return out;
3441};
3442
3443/**
3444 * Copy the values from one vec4 to another
3445 *
3446 * @param {vec4} out the receiving vector
3447 * @param {vec4} a the source vector
3448 * @returns {vec4} out
3449 */
3450vec4.copy = function(out, a) {
3451 out[0] = a[0];
3452 out[1] = a[1];
3453 out[2] = a[2];
3454 out[3] = a[3];
3455 return out;
3456};
3457
3458/**
3459 * Set the components of a vec4 to the given values
3460 *
3461 * @param {vec4} out the receiving vector
3462 * @param {Number} x X component
3463 * @param {Number} y Y component
3464 * @param {Number} z Z component
3465 * @param {Number} w W component
3466 * @returns {vec4} out
3467 */
3468vec4.set = function(out, x, y, z, w) {
3469 out[0] = x;
3470 out[1] = y;
3471 out[2] = z;
3472 out[3] = w;
3473 return out;
3474};
3475
3476/**
3477 * Adds two vec4's
3478 *
3479 * @param {vec4} out the receiving vector
3480 * @param {vec4} a the first operand
3481 * @param {vec4} b the second operand
3482 * @returns {vec4} out
3483 */
3484vec4.add = function(out, a, b) {
3485 out[0] = a[0] + b[0];
3486 out[1] = a[1] + b[1];
3487 out[2] = a[2] + b[2];
3488 out[3] = a[3] + b[3];
3489 return out;
3490};
3491
3492/**
3493 * Subtracts two vec4's
3494 *
3495 * @param {vec4} out the receiving vector
3496 * @param {vec4} a the first operand
3497 * @param {vec4} b the second operand
3498 * @returns {vec4} out
3499 */
3500vec4.sub = vec4.subtract = function(out, a, b) {
3501 out[0] = a[0] - b[0];
3502 out[1] = a[1] - b[1];
3503 out[2] = a[2] - b[2];
3504 out[3] = a[3] - b[3];
3505 return out;
3506};
3507
3508/**
3509 * Multiplies two vec4's
3510 *
3511 * @param {vec4} out the receiving vector
3512 * @param {vec4} a the first operand
3513 * @param {vec4} b the second operand
3514 * @returns {vec4} out
3515 */
3516vec4.mul = vec4.multiply = function(out, a, b) {
3517 out[0] = a[0] * b[0];
3518 out[1] = a[1] * b[1];
3519 out[2] = a[2] * b[2];
3520 out[3] = a[3] * b[3];
3521 return out;
3522};
3523
3524/**
3525 * Divides two vec4's
3526 *
3527 * @param {vec4} out the receiving vector
3528 * @param {vec4} a the first operand
3529 * @param {vec4} b the second operand
3530 * @returns {vec4} out
3531 */
3532vec4.div = vec4.divide = function(out, a, b) {
3533 out[0] = a[0] / b[0];
3534 out[1] = a[1] / b[1];
3535 out[2] = a[2] / b[2];
3536 out[3] = a[3] / b[3];
3537 return out;
3538};
3539
3540/**
3541 * Returns the minimum of two vec4's
3542 *
3543 * @param {vec4} out the receiving vector
3544 * @param {vec4} a the first operand
3545 * @param {vec4} b the second operand
3546 * @returns {vec4} out
3547 */
3548vec4.min = function(out, a, b) {
3549 out[0] = Math.min(a[0], b[0]);
3550 out[1] = Math.min(a[1], b[1]);
3551 out[2] = Math.min(a[2], b[2]);
3552 out[3] = Math.min(a[3], b[3]);
3553 return out;
3554};
3555
3556/**
3557 * Returns the maximum of two vec4's
3558 *
3559 * @param {vec4} out the receiving vector
3560 * @param {vec4} a the first operand
3561 * @param {vec4} b the second operand
3562 * @returns {vec4} out
3563 */
3564vec4.max = function(out, a, b) {
3565 out[0] = Math.max(a[0], b[0]);
3566 out[1] = Math.max(a[1], b[1]);
3567 out[2] = Math.max(a[2], b[2]);
3568 out[3] = Math.max(a[3], b[3]);
3569 return out;
3570};
3571
3572/**
3573 * Scales a vec4 by a scalar number
3574 *
3575 * @param {vec4} out the receiving vector
3576 * @param {vec4} a the vector to scale
3577 * @param {vec4} b amount to scale the vector by
3578 * @returns {vec4} out
3579 */
3580vec4.scale = function(out, a, b) {
3581 out[0] = a[0] * b;
3582 out[1] = a[1] * b;
3583 out[2] = a[2] * b;
3584 out[3] = a[3] * b;
3585 return out;
3586};
3587
3588/**
3589 * Calculates the euclidian distance between two vec4's
3590 *
3591 * @param {vec4} a the first operand
3592 * @param {vec4} b the second operand
3593 * @returns {Number} distance between a and b
3594 */
3595vec4.dist = vec4.distance = function(a, b) {
3596 var x = b[0] - a[0],
3597 y = b[1] - a[1],
3598 z = b[2] - a[2],
3599 w = b[3] - a[3];
3600 return Math.sqrt(x*x + y*y + z*z + w*w);
3601};
3602
3603/**
3604 * Calculates the squared euclidian distance between two vec4's
3605 *
3606 * @param {vec4} a the first operand
3607 * @param {vec4} b the second operand
3608 * @returns {Number} squared distance between a and b
3609 */
3610vec4.sqrDist = vec4.squaredDistance = function(a, b) {
3611 var x = b[0] - a[0],
3612 y = b[1] - a[1],
3613 z = b[2] - a[2],
3614 w = b[3] - a[3];
3615 return x*x + y*y + z*z + w*w;
3616};
3617
3618/**
3619 * Caclulates the length of a vec4
3620 *
3621 * @param {vec4} a vector to calculate length of
3622 * @returns {Number} length of a
3623 */
3624vec4.len = vec4.length = function (a) {
3625 var x = a[0],
3626 y = a[1],
3627 z = a[2],
3628 w = a[3];
3629 return Math.sqrt(x*x + y*y + z*z + w*w);
3630};
3631
3632/**
3633 * Caclulates the squared length of a vec4
3634 *
3635 * @param {vec4} a vector to calculate squared length of
3636 * @returns {Number} squared length of a
3637 */
3638vec4.sqrLen = vec4.squaredLength = function (a) {
3639 var x = a[0],
3640 y = a[1],
3641 z = a[2],
3642 w = a[3];
3643 return x*x + y*y + z*z + w*w;
3644};
3645
3646/**
3647 * Negates the components of a vec4
3648 *
3649 * @param {vec4} out the receiving vector
3650 * @param {vec4} a vector to negate
3651 * @returns {vec4} out
3652 */
3653vec4.negate = function(out, a) {
3654 out[0] = -a[0];
3655 out[1] = -a[1];
3656 out[2] = -a[2];
3657 out[3] = -a[3];
3658 return out;
3659};
3660
3661/**
3662 * Normalize a vec4
3663 *
3664 * @param {vec4} out the receiving vector
3665 * @param {vec4} a vector to normalize
3666 * @returns {vec4} out
3667 */
3668vec4.normalize = function(out, a) {
3669 var x = a[0],
3670 y = a[1],
3671 z = a[2],
3672 w = a[3];
3673 var len = x*x + y*y + z*z + w*w;
3674 if (len > 0) {
3675 len = 1 / Math.sqrt(len);
3676 out[0] = a[0] * len;
3677 out[1] = a[1] * len;
3678 out[2] = a[2] * len;
3679 out[3] = a[3] * len;
3680 }
3681 return out;
3682};
3683
3684/**
3685 * Caclulates the dot product of two vec4's
3686 *
3687 * @param {vec4} a the first operand
3688 * @param {vec4} b the second operand
3689 * @returns {Number} dot product of a and b
3690 */
3691vec4.dot = function (a, b) {
3692 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
3693};
3694
3695/**
3696 * Performs a linear interpolation between two vec4's
3697 *
3698 * @param {vec4} out the receiving vector
3699 * @param {vec4} a the first operand
3700 * @param {vec4} b the second operand
3701 * @param {Number} t interpolation amount between the two inputs
3702 * @returns {vec4} out
3703 */
3704vec4.lerp = function (out, a, b, t) {
3705 var ax = a[0],
3706 ay = a[1],
3707 az = a[2],
3708 aw = a[3];
3709 out[0] = ax + t * (b[0] - ax);
3710 out[1] = ay + t * (b[1] - ay);
3711 out[2] = az + t * (b[2] - az);
3712 out[3] = aw + t * (b[3] - aw);
3713 return out;
3714};
3715
3716/**
3717 * Transforms the vec4 with a mat4.
3718 *
3719 * @param {vec4} out the receiving vector
3720 * @param {vec4} a the vector to transform
3721 * @param {mat4} m matrix to transform with
3722 * @returns {vec4} out
3723 */
3724vec4.transformMat4 = function(out, a, m) {
3725 var x = a[0], y = a[1], z = a[2], w = a[3];
3726 out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
3727 out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
3728 out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
3729 out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
3730 return out;
3731};
3732
3733/**
3734 * Transforms the vec4 with a quat
3735 *
3736 * @param {vec4} out the receiving vector
3737 * @param {vec4} a the vector to transform
3738 * @param {quat} q quaternion to transform with
3739 * @returns {vec4} out
3740 */
3741vec4.transformQuat = function(out, a, q) {
3742 var x = a[0], y = a[1], z = a[2],
3743 qx = q[0], qy = q[1], qz = q[2], qw = q[3],
3744
3745 // calculate quat * vec
3746 ix = qw * x + qy * z - qz * y,
3747 iy = qw * y + qz * x - qx * z,
3748 iz = qw * z + qx * y - qy * x,
3749 iw = -qx * x - qy * y - qz * z;
3750
3751 // calculate result * inverse quat
3752 out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
3753 out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
3754 out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
3755 return out;
3756};
3757
3758/**
3759 * Perform some operation over an array of vec4s.
3760 *
3761 * @param {Array} a the array of vectors to iterate over
3762 * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
3763 * @param {Number} offset Number of elements to skip at the beginning of the array
3764 * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
3765 * @param {Function} fn Function to call for each vector in the array
3766 * @param {Object} [arg] additional argument to pass to fn
3767 * @returns {Array} a
3768 */
3769vec4.forEach = (function() {
3770 var vec = new Float32Array(4);
3771
3772 return function(a, stride, offset, count, fn, arg) {
3773 var i, l;
3774 if(!stride) {
3775 stride = 4;
3776 }
3777
3778 if(!offset) {
3779 offset = 0;
3780 }
3781
3782 if(count) {
3783 l = Math.min((count * stride) + offset, a.length);
3784 } else {
3785 l = a.length;
3786 }
3787
3788 for(i = offset; i < l; i += stride) {
3789 vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
3790 fn(vec, vec, arg);
3791 a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
3792 }
3793
3794 return a;
3795 };
3796})();
3797
3798/**
3799 * Returns a string representation of a vector
3800 *
3801 * @param {vec4} vec vector to represent as a string
3802 * @returns {String} string representation of the vector
3803 */
3804vec4.str = function (a) {
3805 return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
3806};
3807
3808if(typeof(exports) !== 'undefined') {
3809 exports.vec4 = vec4;
3810}
3811;
3812/* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
3813
3814Redistribution and use in source and binary forms, with or without modification,
3815are permitted provided that the following conditions are met:
3816
3817 * Redistributions of source code must retain the above copyright notice, this
3818 list of conditions and the following disclaimer.
3819 * Redistributions in binary form must reproduce the above copyright notice,
3820 this list of conditions and the following disclaimer in the documentation
3821 and/or other materials provided with the distribution.
3822
3823THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
3824ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3825WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3826DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
3827ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3828(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3829LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3830ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3831(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3832SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
3833
3834/**
3835 * @class 2x2 Matrix
3836 * @name mat2
3837 */
3838
3839var mat2 = {};
3840
3841var mat2Identity = new Float32Array([
3842 1, 0,
3843 0, 1
3844]);
3845
3846if(!GLMAT_EPSILON) {
3847 var GLMAT_EPSILON = 0.000001;
3848}
3849
3850/**
3851 * Creates a new identity mat2
3852 *
3853 * @returns {mat2} a new 2x2 matrix
3854 */
3855mat2.create = function() {
3856 return new Float32Array(mat2Identity);
3857};
3858
3859/**
3860 * Creates a new mat2 initialized with values from an existing matrix
3861 *
3862 * @param {mat2} a matrix to clone
3863 * @returns {mat2} a new 2x2 matrix
3864 */
3865mat2.clone = function(a) {
3866 var out = new Float32Array(4);
3867 out[0] = a[0];
3868 out[1] = a[1];
3869 out[2] = a[2];
3870 out[3] = a[3];
3871 return out;
3872};
3873
3874/**
3875 * Copy the values from one mat2 to another
3876 *
3877 * @param {mat2} out the receiving matrix
3878 * @param {mat2} a the source matrix
3879 * @returns {mat2} out
3880 */
3881mat2.copy = function(out, a) {
3882 out[0] = a[0];
3883 out[1] = a[1];
3884 out[2] = a[2];
3885 out[3] = a[3];
3886 return out;
3887};
3888
3889/**
3890 * Set a mat2 to the identity matrix
3891 *
3892 * @param {mat2} out the receiving matrix
3893 * @returns {mat2} out
3894 */
3895mat2.identity = function(out) {
3896 out[0] = 1;
3897 out[1] = 0;
3898 out[2] = 0;
3899 out[3] = 1;
3900 return out;
3901};
3902
3903/**
3904 * Transpose the values of a mat2
3905 *
3906 * @param {mat2} out the receiving matrix
3907 * @param {mat2} a the source matrix
3908 * @returns {mat2} out
3909 */
3910mat2.transpose = function(out, a) {
3911 // If we are transposing ourselves we can skip a few steps but have to cache some values
3912 if (out === a) {
3913 var a1 = a[1];
3914 out[1] = a[2];
3915 out[2] = a1;
3916 } else {
3917 out[0] = a[0];
3918 out[1] = a[2];
3919 out[2] = a[1];
3920 out[3] = a[3];
3921 }
3922
3923 return out;
3924};
3925
3926/**
3927 * Inverts a mat2
3928 *
3929 * @param {mat2} out the receiving matrix
3930 * @param {mat2} a the source matrix
3931 * @returns {mat2} out
3932 */
3933mat2.invert = function(out, a) {
3934 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
3935
3936 // Calculate the determinant
3937 det = a0 * a3 - a2 * a1;
3938
3939 if (!det) {
3940 return null;
3941 }
3942 det = 1.0 / det;
3943
3944 out[0] = a3 * det;
3945 out[1] = -a1 * det;
3946 out[2] = -a2 * det;
3947 out[3] = a0 * det;
3948
3949 return out;
3950};
3951
3952/**
3953 * Caclulates the adjugate of a mat2
3954 *
3955 * @param {mat2} out the receiving matrix
3956 * @param {mat2} a the source matrix
3957 * @returns {mat2} out
3958 */
3959mat2.adjoint = function(out, a) {
3960 // Caching this value is nessecary if out == a
3961 var a0 = a[0];
3962 out[0] = a[3];
3963 out[1] = -a[1];
3964 out[2] = -a[2];
3965 out[3] = a0;
3966
3967 return out;
3968};
3969
3970/**
3971 * Calculates the determinant of a mat2
3972 *
3973 * @param {mat2} a the source matrix
3974 * @returns {Number} determinant of a
3975 */
3976mat2.determinant = function (a) {
3977 return a[0] * a[3] - a[2] * a[1];
3978};
3979
3980/**
3981 * Multiplies two mat2's
3982 *
3983 * @param {mat2} out the receiving matrix
3984 * @param {mat2} a the first operand
3985 * @param {mat2} b the second operand
3986 * @returns {mat2} out
3987 */
3988mat2.mul = mat2.multiply = function (out, a, b) {
3989 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
3990 var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
3991 out[0] = a0 * b0 + a1 * b2;
3992 out[1] = a0 * b1 + a1 * b3;
3993 out[2] = a2 * b0 + a3 * b2;
3994 out[3] = a2 * b1 + a3 * b3;
3995 return out;
3996};
3997
3998/**
3999 * Rotates a mat2 by the given angle
4000 *
4001 * @param {mat2} out the receiving matrix
4002 * @param {mat2} a the matrix to rotate
4003 * @param {mat2} rad the angle to rotate the matrix by
4004 * @returns {mat2} out
4005 */
4006mat2.rotate = function (out, a, rad) {
4007 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
4008 s = Math.sin(rad),
4009 c = Math.cos(rad);
4010 out[0] = a0 * c + a1 * s;
4011 out[1] = a0 * -s + a1 * c;
4012 out[2] = a2 * c + a3 * s;
4013 out[3] = a2 * -s + a3 * c;
4014 return out;
4015};
4016
4017/**
4018 * Scales the mat2 by the dimensions in the given vec2
4019 *
4020 * @param {mat2} out the receiving matrix
4021 * @param {mat2} a the matrix to rotate
4022 * @param {mat2} v the vec2 to scale the matrix by
4023 * @returns {mat2} out
4024 **/
4025mat2.scale = function(out, a, v) {
4026 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
4027 v0 = v[0], v1 = v[1];
4028 out[0] = a0 * v0;
4029 out[1] = a1 * v1;
4030 out[2] = a2 * v0;
4031 out[3] = a3 * v1;
4032 return out;
4033};
4034
4035/**
4036 * Returns a string representation of a mat2
4037 *
4038 * @param {mat2} mat matrix to represent as a string
4039 * @returns {String} string representation of the matrix
4040 */
4041mat2.str = function (a) {
4042 return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
4043};
4044
4045if(typeof(exports) !== 'undefined') {
4046 exports.mat2 = mat2;
4047}
4048;
4049/* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
4050
4051Redistribution and use in source and binary forms, with or without modification,
4052are permitted provided that the following conditions are met:
4053
4054 * Redistributions of source code must retain the above copyright notice, this
4055 list of conditions and the following disclaimer.
4056 * Redistributions in binary form must reproduce the above copyright notice,
4057 this list of conditions and the following disclaimer in the documentation
4058 and/or other materials provided with the distribution.
4059
4060THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
4061ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
4062WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
4063DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
4064ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4065(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4066LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
4067ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4068(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4069SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
4070
4071/**
4072 * @class 3x3 Matrix
4073 * @name mat3
4074 */
4075
4076var mat3 = {};
4077
4078var mat3Identity = new Float32Array([
4079 1, 0, 0,
4080 0, 1, 0,
4081 0, 0, 1
4082]);
4083
4084if(!GLMAT_EPSILON) {
4085 var GLMAT_EPSILON = 0.000001;
4086}
4087
4088/**
4089 * Creates a new identity mat3
4090 *
4091 * @returns {mat3} a new 3x3 matrix
4092 */
4093mat3.create = function() {
4094 return new Float32Array(mat3Identity);
4095};
4096
4097/**
4098 * Creates a new mat3 initialized with values from an existing matrix
4099 *
4100 * @param {mat3} a matrix to clone
4101 * @returns {mat3} a new 3x3 matrix
4102 */
4103mat3.clone = function(a) {
4104 var out = new Float32Array(9);
4105 out[0] = a[0];
4106 out[1] = a[1];
4107 out[2] = a[2];
4108 out[3] = a[3];
4109 out[4] = a[4];
4110 out[5] = a[5];
4111 out[6] = a[6];
4112 out[7] = a[7];
4113 out[8] = a[8];
4114 return out;
4115};
4116
4117/**
4118 * Copy the values from one mat3 to another
4119 *
4120 * @param {mat3} out the receiving matrix
4121 * @param {mat3} a the source matrix
4122 * @returns {mat3} out
4123 */
4124mat3.copy = function(out, a) {
4125 out[0] = a[0];
4126 out[1] = a[1];
4127 out[2] = a[2];
4128 out[3] = a[3];
4129 out[4] = a[4];
4130 out[5] = a[5];
4131 out[6] = a[6];
4132 out[7] = a[7];
4133 out[8] = a[8];
4134 return out;
4135};
4136
4137/**
4138 * Set a mat3 to the identity matrix
4139 *
4140 * @param {mat3} out the receiving matrix
4141 * @returns {mat3} out
4142 */
4143mat3.identity = function(out) {
4144 out[0] = 1;
4145 out[1] = 0;
4146 out[2] = 0;
4147 out[3] = 0;
4148 out[4] = 1;
4149 out[5] = 0;
4150 out[6] = 0;
4151 out[7] = 0;
4152 out[8] = 1;
4153 return out;
4154};
4155
4156/**
4157 * Transpose the values of a mat3
4158 *
4159 * @param {mat3} out the receiving matrix
4160 * @param {mat3} a the source matrix
4161 * @returns {mat3} out
4162 */
4163mat3.transpose = function(out, a) {
4164 // If we are transposing ourselves we can skip a few steps but have to cache some values
4165 if (out === a) {
4166 var a01 = a[1], a02 = a[2], a12 = a[5];
4167 out[1] = a[3];
4168 out[2] = a[6];
4169 out[3] = a01;
4170 out[5] = a[7];
4171 out[6] = a02;
4172 out[7] = a12;
4173 } else {
4174 out[0] = a[0];
4175 out[1] = a[3];
4176 out[2] = a[6];
4177 out[3] = a[1];
4178 out[4] = a[4];
4179 out[5] = a[7];
4180 out[6] = a[2];
4181 out[7] = a[5];
4182 out[8] = a[8];
4183 }
4184
4185 return out;
4186};
4187
4188/**
4189 * Inverts a mat3
4190 *
4191 * @param {mat3} out the receiving matrix
4192 * @param {mat3} a the source matrix
4193 * @returns {mat3} out
4194 */
4195mat3.invert = function(out, a) {
4196 var a00 = a[0], a01 = a[1], a02 = a[2],
4197 a10 = a[3], a11 = a[4], a12 = a[5],
4198 a20 = a[6], a21 = a[7], a22 = a[8],
4199
4200 b01 = a22 * a11 - a12 * a21,
4201 b11 = -a22 * a10 + a12 * a20,
4202 b21 = a21 * a10 - a11 * a20,
4203
4204 // Calculate the determinant
4205 det = a00 * b01 + a01 * b11 + a02 * b21;
4206
4207 if (!det) {
4208 return null;
4209 }
4210 det = 1.0 / det;
4211
4212 out[0] = b01 * det;
4213 out[1] = (-a22 * a01 + a02 * a21) * det;
4214 out[2] = (a12 * a01 - a02 * a11) * det;
4215 out[3] = b11 * det;
4216 out[4] = (a22 * a00 - a02 * a20) * det;
4217 out[5] = (-a12 * a00 + a02 * a10) * det;
4218 out[6] = b21 * det;
4219 out[7] = (-a21 * a00 + a01 * a20) * det;
4220 out[8] = (a11 * a00 - a01 * a10) * det;
4221 return out;
4222};
4223
4224/**
4225 * Caclulates the adjugate of a mat3
4226 *
4227 * @param {mat3} out the receiving matrix
4228 * @param {mat3} a the source matrix
4229 * @returns {mat3} out
4230 */
4231mat3.adjoint = function(out, a) {
4232 var a00 = a[0], a01 = a[1], a02 = a[2],
4233 a10 = a[3], a11 = a[4], a12 = a[5],
4234 a20 = a[6], a21 = a[7], a22 = a[8];
4235
4236 out[0] = (a11 * a22 - a12 * a21);
4237 out[1] = (a02 * a21 - a01 * a22);
4238 out[2] = (a01 * a12 - a02 * a11);
4239 out[3] = (a12 * a20 - a10 * a22);
4240 out[4] = (a00 * a22 - a02 * a20);
4241 out[5] = (a02 * a10 - a00 * a12);
4242 out[6] = (a10 * a21 - a11 * a20);
4243 out[7] = (a01 * a20 - a00 * a21);
4244 out[8] = (a00 * a11 - a01 * a10);
4245 return out;
4246};
4247
4248/**
4249 * Calculates the determinant of a mat3
4250 *
4251 * @param {mat3} a the source matrix
4252 * @returns {Number} determinant of a
4253 */
4254mat3.determinant = function (a) {
4255 var a00 = a[0], a01 = a[1], a02 = a[2],
4256 a10 = a[3], a11 = a[4], a12 = a[5],
4257 a20 = a[6], a21 = a[7], a22 = a[8];
4258
4259 return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
4260};
4261
4262/**
4263 * Multiplies two mat3's
4264 *
4265 * @param {mat3} out the receiving matrix
4266 * @param {mat3} a the first operand
4267 * @param {mat3} b the second operand
4268 * @returns {mat3} out
4269 */
4270mat3.mul = mat3.multiply = function (out, a, b) {
4271 var a00 = a[0], a01 = a[1], a02 = a[2],
4272 a10 = a[3], a11 = a[4], a12 = a[5],
4273 a20 = a[6], a21 = a[7], a22 = a[8],
4274
4275 b00 = b[0], b01 = b[1], b02 = b[2],
4276 b10 = b[3], b11 = b[4], b12 = b[5],
4277 b20 = b[6], b21 = b[7], b22 = b[8];
4278
4279 out[0] = b00 * a00 + b01 * a10 + b02 * a20;
4280 out[1] = b00 * a01 + b01 * a11 + b02 * a21;
4281 out[2] = b00 * a02 + b01 * a12 + b02 * a22;
4282
4283 out[3] = b10 * a00 + b11 * a10 + b12 * a20;
4284 out[4] = b10 * a01 + b11 * a11 + b12 * a21;
4285 out[5] = b10 * a02 + b11 * a12 + b12 * a22;
4286
4287 out[6] = b20 * a00 + b21 * a10 + b22 * a20;
4288 out[7] = b20 * a01 + b21 * a11 + b22 * a21;
4289 out[8] = b20 * a02 + b21 * a12 + b22 * a22;
4290 return out;
4291};
4292
4293/**
4294 * Returns a string representation of a mat3
4295 *
4296 * @param {mat3} mat matrix to represent as a string
4297 * @returns {String} string representation of the matrix
4298 */
4299mat3.str = function (a) {
4300 return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
4301 a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
4302 a[6] + ', ' + a[7] + ', ' + a[8] + ')';
4303};
4304
4305if(typeof(exports) !== 'undefined') {
4306 exports.mat3 = mat3;
4307}
4308;
4309/* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
4310
4311Redistribution and use in source and binary forms, with or without modification,
4312are permitted provided that the following conditions are met:
4313
4314 * Redistributions of source code must retain the above copyright notice, this
4315 list of conditions and the following disclaimer.
4316 * Redistributions in binary form must reproduce the above copyright notice,
4317 this list of conditions and the following disclaimer in the documentation
4318 and/or other materials provided with the distribution.
4319
4320THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
4321ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
4322WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
4323DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
4324ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4325(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4326LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
4327ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4328(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4329SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
4330
4331/**
4332 * @class 4x4 Matrix
4333 * @name mat4
4334 */
4335
4336var mat4 = {};
4337
4338var mat4Identity = new Float32Array([
4339 1, 0, 0, 0,
4340 0, 1, 0, 0,
4341 0, 0, 1, 0,
4342 0, 0, 0, 1
4343]);
4344
4345if(!GLMAT_EPSILON) {
4346 var GLMAT_EPSILON = 0.000001;
4347}
4348
4349/**
4350 * Creates a new identity mat4
4351 *
4352 * @returns {mat4} a new 4x4 matrix
4353 */
4354mat4.create = function() {
4355 return new Float32Array(mat4Identity);
4356};
4357
4358/**
4359 * Creates a new mat4 initialized with values from an existing matrix
4360 *
4361 * @param {mat4} a matrix to clone
4362 * @returns {mat4} a new 4x4 matrix
4363 */
4364mat4.clone = function(a) {
4365 var out = new Float32Array(16);
4366 out[0] = a[0];
4367 out[1] = a[1];
4368 out[2] = a[2];
4369 out[3] = a[3];
4370 out[4] = a[4];
4371 out[5] = a[5];
4372 out[6] = a[6];
4373 out[7] = a[7];
4374 out[8] = a[8];
4375 out[9] = a[9];
4376 out[10] = a[10];
4377 out[11] = a[11];
4378 out[12] = a[12];
4379 out[13] = a[13];
4380 out[14] = a[14];
4381 out[15] = a[15];
4382 return out;
4383};
4384
4385/**
4386 * Copy the values from one mat4 to another
4387 *
4388 * @param {mat4} out the receiving matrix
4389 * @param {mat4} a the source matrix
4390 * @returns {mat4} out
4391 */
4392mat4.copy = function(out, a) {
4393 out[0] = a[0];
4394 out[1] = a[1];
4395 out[2] = a[2];
4396 out[3] = a[3];
4397 out[4] = a[4];
4398 out[5] = a[5];
4399 out[6] = a[6];
4400 out[7] = a[7];
4401 out[8] = a[8];
4402 out[9] = a[9];
4403 out[10] = a[10];
4404 out[11] = a[11];
4405 out[12] = a[12];
4406 out[13] = a[13];
4407 out[14] = a[14];
4408 out[15] = a[15];
4409 return out;
4410};
4411
4412/**
4413 * Set a mat4 to the identity matrix
4414 *
4415 * @param {mat4} out the receiving matrix
4416 * @returns {mat4} out
4417 */
4418mat4.identity = function(out) {
4419 out[0] = 1;
4420 out[1] = 0;
4421 out[2] = 0;
4422 out[3] = 0;
4423 out[4] = 0;
4424 out[5] = 1;
4425 out[6] = 0;
4426 out[7] = 0;
4427 out[8] = 0;
4428 out[9] = 0;
4429 out[10] = 1;
4430 out[11] = 0;
4431 out[12] = 0;
4432 out[13] = 0;
4433 out[14] = 0;
4434 out[15] = 1;
4435 return out;
4436};
4437
4438/**
4439 * Transpose the values of a mat4
4440 *
4441 * @param {mat4} out the receiving matrix
4442 * @param {mat4} a the source matrix
4443 * @returns {mat4} out
4444 */
4445mat4.transpose = function(out, a) {
4446 // If we are transposing ourselves we can skip a few steps but have to cache some values
4447 if (out === a) {
4448 var a01 = a[1], a02 = a[2], a03 = a[3],
4449 a12 = a[6], a13 = a[7],
4450 a23 = a[11];
4451
4452 out[1] = a[4];
4453 out[2] = a[8];
4454 out[3] = a[12];
4455 out[4] = a01;
4456 out[6] = a[9];
4457 out[7] = a[13];
4458 out[8] = a02;
4459 out[9] = a12;
4460 out[11] = a[14];
4461 out[12] = a03;
4462 out[13] = a13;
4463 out[14] = a23;
4464 } else {
4465 out[0] = a[0];
4466 out[1] = a[4];
4467 out[2] = a[8];
4468 out[3] = a[12];
4469 out[4] = a[1];
4470 out[5] = a[5];
4471 out[6] = a[9];
4472 out[7] = a[13];
4473 out[8] = a[2];
4474 out[9] = a[6];
4475 out[10] = a[10];
4476 out[11] = a[14];
4477 out[12] = a[3];
4478 out[13] = a[7];
4479 out[14] = a[11];
4480 out[15] = a[15];
4481 }
4482
4483 return out;
4484};
4485
4486/**
4487 * Inverts a mat4
4488 *
4489 * @param {mat4} out the receiving matrix
4490 * @param {mat4} a the source matrix
4491 * @returns {mat4} out
4492 */
4493mat4.invert = function(out, a) {
4494 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
4495 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
4496 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
4497 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
4498
4499 b00 = a00 * a11 - a01 * a10,
4500 b01 = a00 * a12 - a02 * a10,
4501 b02 = a00 * a13 - a03 * a10,
4502 b03 = a01 * a12 - a02 * a11,
4503 b04 = a01 * a13 - a03 * a11,
4504 b05 = a02 * a13 - a03 * a12,
4505 b06 = a20 * a31 - a21 * a30,
4506 b07 = a20 * a32 - a22 * a30,
4507 b08 = a20 * a33 - a23 * a30,
4508 b09 = a21 * a32 - a22 * a31,
4509 b10 = a21 * a33 - a23 * a31,
4510 b11 = a22 * a33 - a23 * a32,
4511
4512 // Calculate the determinant
4513 det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
4514
4515 if (!det) {
4516 return null;
4517 }
4518 det = 1.0 / det;
4519
4520 out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
4521 out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
4522 out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
4523 out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
4524 out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
4525 out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
4526 out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
4527 out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
4528 out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
4529 out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
4530 out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
4531 out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
4532 out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
4533 out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
4534 out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
4535 out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
4536
4537 return out;
4538};
4539
4540/**
4541 * Caclulates the adjugate of a mat4
4542 *
4543 * @param {mat4} out the receiving matrix
4544 * @param {mat4} a the source matrix
4545 * @returns {mat4} out
4546 */
4547mat4.adjoint = function(out, a) {
4548 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
4549 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
4550 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
4551 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
4552
4553 out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
4554 out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
4555 out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
4556 out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
4557 out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
4558 out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
4559 out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
4560 out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
4561 out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
4562 out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
4563 out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
4564 out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
4565 out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
4566 out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
4567 out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
4568 out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
4569 return out;
4570};
4571
4572/**
4573 * Calculates the determinant of a mat4
4574 *
4575 * @param {mat4} a the source matrix
4576 * @returns {Number} determinant of a
4577 */
4578mat4.determinant = function (a) {
4579 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
4580 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
4581 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
4582 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
4583
4584 b00 = a00 * a11 - a01 * a10,
4585 b01 = a00 * a12 - a02 * a10,
4586 b02 = a00 * a13 - a03 * a10,
4587 b03 = a01 * a12 - a02 * a11,
4588 b04 = a01 * a13 - a03 * a11,
4589 b05 = a02 * a13 - a03 * a12,
4590 b06 = a20 * a31 - a21 * a30,
4591 b07 = a20 * a32 - a22 * a30,
4592 b08 = a20 * a33 - a23 * a30,
4593 b09 = a21 * a32 - a22 * a31,
4594 b10 = a21 * a33 - a23 * a31,
4595 b11 = a22 * a33 - a23 * a32;
4596
4597 // Calculate the determinant
4598 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
4599};
4600
4601/**
4602 * Multiplies two mat4's
4603 *
4604 * @param {mat4} out the receiving matrix
4605 * @param {mat4} a the first operand
4606 * @param {mat4} b the second operand
4607 * @returns {mat4} out
4608 */
4609mat4.mul = mat4.multiply = function (out, a, b) {
4610 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
4611 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
4612 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
4613 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
4614
4615 // Cache only the current line of the second matrix
4616 var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
4617 out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
4618 out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
4619 out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
4620 out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
4621
4622 b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
4623 out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
4624 out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
4625 out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
4626 out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
4627
4628 b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
4629 out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
4630 out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
4631 out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
4632 out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
4633
4634 b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
4635 out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
4636 out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
4637 out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
4638 out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
4639 return out;
4640};
4641
4642/**
4643 * Translate a mat4 by the given vector
4644 *
4645 * @param {mat4} out the receiving matrix
4646 * @param {mat4} a the matrix to translate
4647 * @param {vec3} v vector to translate by
4648 * @returns {mat4} out
4649 */
4650mat4.translate = function (out, a, v) {
4651 var x = v[0], y = v[1], z = v[2],
4652 a00, a01, a02, a03,
4653 a10, a11, a12, a13,
4654 a20, a21, a22, a23;
4655
4656 if (a === out) {
4657 out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
4658 out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
4659 out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
4660 out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
4661 } else {
4662 a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
4663 a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
4664 a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
4665
4666 out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
4667 out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
4668 out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
4669
4670 out[12] = a00 * x + a10 * y + a20 * z + a[12];
4671 out[13] = a01 * x + a11 * y + a21 * z + a[13];
4672 out[14] = a02 * x + a12 * y + a22 * z + a[14];
4673 out[15] = a03 * x + a13 * y + a23 * z + a[15];
4674 }
4675
4676 return out;
4677};
4678
4679/**
4680 * Scales the mat4 by the dimensions in the given vec3
4681 *
4682 * @param {mat4} out the receiving matrix
4683 * @param {mat4} a the matrix to scale
4684 * @param {vec3} v the vec3 to scale the matrix by
4685 * @returns {mat4} out
4686 **/
4687mat4.scale = function(out, a, v) {
4688 var x = v[0], y = v[1], z = v[2];
4689
4690 out[0] = a[0] * x;
4691 out[1] = a[1] * x;
4692 out[2] = a[2] * x;
4693 out[3] = a[3] * x;
4694 out[4] = a[4] * y;
4695 out[5] = a[5] * y;
4696 out[6] = a[6] * y;
4697 out[7] = a[7] * y;
4698 out[8] = a[8] * z;
4699 out[9] = a[9] * z;
4700 out[10] = a[10] * z;
4701 out[11] = a[11] * z;
4702 out[12] = a[12];
4703 out[13] = a[13];
4704 out[14] = a[14];
4705 out[15] = a[15];
4706 return out;
4707};
4708
4709/**
4710 * Rotates a mat4 by the given angle
4711 *
4712 * @param {mat4} out the receiving matrix
4713 * @param {mat4} a the matrix to rotate
4714 * @param {Number} rad the angle to rotate the matrix by
4715 * @param {vec3} axis the axis to rotate around
4716 * @returns {mat4} out
4717 */
4718mat4.rotate = function (out, a, rad, axis) {
4719 var x = axis[0], y = axis[1], z = axis[2],
4720 len = Math.sqrt(x * x + y * y + z * z),
4721 s, c, t,
4722 a00, a01, a02, a03,
4723 a10, a11, a12, a13,
4724 a20, a21, a22, a23,
4725 b00, b01, b02,
4726 b10, b11, b12,
4727 b20, b21, b22;
4728
4729 if (Math.abs(len) < GLMAT_EPSILON) { return null; }
4730
4731 len = 1 / len;
4732 x *= len;
4733 y *= len;
4734 z *= len;
4735
4736 s = Math.sin(rad);
4737 c = Math.cos(rad);
4738 t = 1 - c;
4739
4740 a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
4741 a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
4742 a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
4743
4744 // Construct the elements of the rotation matrix
4745 b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
4746 b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
4747 b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
4748
4749 // Perform rotation-specific matrix multiplication
4750 out[0] = a00 * b00 + a10 * b01 + a20 * b02;
4751 out[1] = a01 * b00 + a11 * b01 + a21 * b02;
4752 out[2] = a02 * b00 + a12 * b01 + a22 * b02;
4753 out[3] = a03 * b00 + a13 * b01 + a23 * b02;
4754 out[4] = a00 * b10 + a10 * b11 + a20 * b12;
4755 out[5] = a01 * b10 + a11 * b11 + a21 * b12;
4756 out[6] = a02 * b10 + a12 * b11 + a22 * b12;
4757 out[7] = a03 * b10 + a13 * b11 + a23 * b12;
4758 out[8] = a00 * b20 + a10 * b21 + a20 * b22;
4759 out[9] = a01 * b20 + a11 * b21 + a21 * b22;
4760 out[10] = a02 * b20 + a12 * b21 + a22 * b22;
4761 out[11] = a03 * b20 + a13 * b21 + a23 * b22;
4762
4763 if (a !== out) { // If the source and destination differ, copy the unchanged last row
4764 out[12] = a[12];
4765 out[13] = a[13];
4766 out[14] = a[14];
4767 out[15] = a[15];
4768 }
4769 return out;
4770};
4771
4772/**
4773 * Rotates a matrix by the given angle around the X axis
4774 *
4775 * @param {mat4} out the receiving matrix
4776 * @param {mat4} a the matrix to rotate
4777 * @param {Number} rad the angle to rotate the matrix by
4778 * @returns {mat4} out
4779 */
4780mat4.rotateX = function (out, a, rad) {
4781 var s = Math.sin(rad),
4782 c = Math.cos(rad),
4783 a10 = a[4],
4784 a11 = a[5],
4785 a12 = a[6],
4786 a13 = a[7],
4787 a20 = a[8],
4788 a21 = a[9],
4789 a22 = a[10],
4790 a23 = a[11];
4791
4792 if (a !== out) { // If the source and destination differ, copy the unchanged rows
4793 out[0] = a[0];
4794 out[1] = a[1];
4795 out[2] = a[2];
4796 out[3] = a[3];
4797 out[12] = a[12];
4798 out[13] = a[13];
4799 out[14] = a[14];
4800 out[15] = a[15];
4801 }
4802
4803 // Perform axis-specific matrix multiplication
4804 out[4] = a10 * c + a20 * s;
4805 out[5] = a11 * c + a21 * s;
4806 out[6] = a12 * c + a22 * s;
4807 out[7] = a13 * c + a23 * s;
4808 out[8] = a20 * c - a10 * s;
4809 out[9] = a21 * c - a11 * s;
4810 out[10] = a22 * c - a12 * s;
4811 out[11] = a23 * c - a13 * s;
4812 return out;
4813};
4814
4815/**
4816 * Rotates a matrix by the given angle around the Y axis
4817 *
4818 * @param {mat4} out the receiving matrix
4819 * @param {mat4} a the matrix to rotate
4820 * @param {Number} rad the angle to rotate the matrix by
4821 * @returns {mat4} out
4822 */
4823mat4.rotateY = function (out, a, rad) {
4824 var s = Math.sin(rad),
4825 c = Math.cos(rad),
4826 a00 = a[0],
4827 a01 = a[1],
4828 a02 = a[2],
4829 a03 = a[3],
4830 a20 = a[8],
4831 a21 = a[9],
4832 a22 = a[10],
4833 a23 = a[11];
4834
4835 if (a !== out) { // If the source and destination differ, copy the unchanged rows
4836 out[4] = a[4];
4837 out[5] = a[5];
4838 out[6] = a[6];
4839 out[7] = a[7];
4840 out[12] = a[12];
4841 out[13] = a[13];
4842 out[14] = a[14];
4843 out[15] = a[15];
4844 }
4845
4846 // Perform axis-specific matrix multiplication
4847 out[0] = a00 * c - a20 * s;
4848 out[1] = a01 * c - a21 * s;
4849 out[2] = a02 * c - a22 * s;
4850 out[3] = a03 * c - a23 * s;
4851 out[8] = a00 * s + a20 * c;
4852 out[9] = a01 * s + a21 * c;
4853 out[10] = a02 * s + a22 * c;
4854 out[11] = a03 * s + a23 * c;
4855 return out;
4856};
4857
4858/**
4859 * Rotates a matrix by the given angle around the Z axis
4860 *
4861 * @param {mat4} out the receiving matrix
4862 * @param {mat4} a the matrix to rotate
4863 * @param {Number} rad the angle to rotate the matrix by
4864 * @returns {mat4} out
4865 */
4866mat4.rotateZ = function (out, a, rad) {
4867 var s = Math.sin(rad),
4868 c = Math.cos(rad),
4869 a00 = a[0],
4870 a01 = a[1],
4871 a02 = a[2],
4872 a03 = a[3],
4873 a10 = a[4],
4874 a11 = a[5],
4875 a12 = a[6],
4876 a13 = a[7];
4877
4878 if (a !== out) { // If the source and destination differ, copy the unchanged last row
4879 out[8] = a[8];
4880 out[9] = a[9];
4881 out[10] = a[10];
4882 out[11] = a[11];
4883 out[12] = a[12];
4884 out[13] = a[13];
4885 out[14] = a[14];
4886 out[15] = a[15];
4887 }
4888
4889 // Perform axis-specific matrix multiplication
4890 out[0] = a00 * c + a10 * s;
4891 out[1] = a01 * c + a11 * s;
4892 out[2] = a02 * c + a12 * s;
4893 out[3] = a03 * c + a13 * s;
4894 out[4] = a10 * c - a00 * s;
4895 out[5] = a11 * c - a01 * s;
4896 out[6] = a12 * c - a02 * s;
4897 out[7] = a13 * c - a03 * s;
4898 return out;
4899};
4900
4901/**
4902 * Creates a matrix from a quaternion rotation and vector translation
4903 * This is equivalent to (but much faster than):
4904 *
4905 * mat4.identity(dest);
4906 * mat4.translate(dest, vec);
4907 * var quatMat = mat4.create();
4908 * quat4.toMat4(quat, quatMat);
4909 * mat4.multiply(dest, quatMat);
4910 *
4911 * @param {mat4} out mat4 receiving operation result
4912 * @param {quat4} q Rotation quaternion
4913 * @param {vec3} v Translation vector
4914 * @returns {mat4} out
4915 */
4916mat4.fromRotationTranslation = function (out, q, v) {
4917 // Quaternion math
4918 var x = q[0], y = q[1], z = q[2], w = q[3],
4919 x2 = x + x,
4920 y2 = y + y,
4921 z2 = z + z,
4922
4923 xx = x * x2,
4924 xy = x * y2,
4925 xz = x * z2,
4926 yy = y * y2,
4927 yz = y * z2,
4928 zz = z * z2,
4929 wx = w * x2,
4930 wy = w * y2,
4931 wz = w * z2;
4932
4933 out[0] = 1 - (yy + zz);
4934 out[1] = xy + wz;
4935 out[2] = xz - wy;
4936 out[3] = 0;
4937 out[4] = xy - wz;
4938 out[5] = 1 - (xx + zz);
4939 out[6] = yz + wx;
4940 out[7] = 0;
4941 out[8] = xz + wy;
4942 out[9] = yz - wx;
4943 out[10] = 1 - (xx + yy);
4944 out[11] = 0;
4945 out[12] = v[0];
4946 out[13] = v[1];
4947 out[14] = v[2];
4948 out[15] = 1;
4949
4950 return out;
4951};
4952
4953/**
4954 * Generates a frustum matrix with the given bounds
4955 *
4956 * @param {mat4} out mat4 frustum matrix will be written into
4957 * @param {Number} left Left bound of the frustum
4958 * @param {Number} right Right bound of the frustum
4959 * @param {Number} bottom Bottom bound of the frustum
4960 * @param {Number} top Top bound of the frustum
4961 * @param {Number} near Near bound of the frustum
4962 * @param {Number} far Far bound of the frustum
4963 * @returns {mat4} out
4964 */
4965mat4.frustum = function (out, left, right, bottom, top, near, far) {
4966 var rl = 1 / (right - left),
4967 tb = 1 / (top - bottom),
4968 nf = 1 / (near - far);
4969 out[0] = (near * 2) * rl;
4970 out[1] = 0;
4971 out[2] = 0;
4972 out[3] = 0;
4973 out[4] = 0;
4974 out[5] = (near * 2) * tb;
4975 out[6] = 0;
4976 out[7] = 0;
4977 out[8] = (right + left) * rl;
4978 out[9] = (top + bottom) * tb;
4979 out[10] = (far + near) * nf;
4980 out[11] = -1;
4981 out[12] = 0;
4982 out[13] = 0;
4983 out[14] = (far * near * 2) * nf;
4984 out[15] = 0;
4985 return out;
4986};
4987
4988/**
4989 * Generates a perspective projection matrix with the given bounds
4990 *
4991 * @param {mat4} out mat4 frustum matrix will be written into
4992 * @param {number} fovy Vertical field of view in radians
4993 * @param {number} aspect Aspect ratio. typically viewport width/height
4994 * @param {number} near Near bound of the frustum
4995 * @param {number} far Far bound of the frustum
4996 * @returns {mat4} out
4997 */
4998mat4.perspective = function (out, fovy, aspect, near, far) {
4999 var f = 1.0 / Math.tan(fovy / 2),
5000 nf = 1 / (near - far);
5001 out[0] = f / aspect;
5002 out[1] = 0;
5003 out[2] = 0;
5004 out[3] = 0;
5005 out[4] = 0;
5006 out[5] = f;
5007 out[6] = 0;
5008 out[7] = 0;
5009 out[8] = 0;
5010 out[9] = 0;
5011 out[10] = (far + near) * nf;
5012 out[11] = -1;
5013 out[12] = 0;
5014 out[13] = 0;
5015 out[14] = (2 * far * near) * nf;
5016 out[15] = 0;
5017 return out;
5018};
5019
5020/**
5021 * Generates a orthogonal projection matrix with the given bounds
5022 *
5023 * @param {mat4} out mat4 frustum matrix will be written into
5024 * @param {number} left Left bound of the frustum
5025 * @param {number} right Right bound of the frustum
5026 * @param {number} bottom Bottom bound of the frustum
5027 * @param {number} top Top bound of the frustum
5028 * @param {number} near Near bound of the frustum
5029 * @param {number} far Far bound of the frustum
5030 * @returns {mat4} out
5031 */
5032mat4.ortho = function (out, left, right, bottom, top, near, far) {
5033 var lr = 1 / (left - right),
5034 bt = 1 / (bottom - top),
5035 nf = 1 / (near - far);
5036 out[0] = -2 * lr;
5037 out[1] = 0;
5038 out[2] = 0;
5039 out[3] = 0;
5040 out[4] = 0;
5041 out[5] = -2 * bt;
5042 out[6] = 0;
5043 out[7] = 0;
5044 out[8] = 0;
5045 out[9] = 0;
5046 out[10] = 2 * nf;
5047 out[11] = 0;
5048 out[12] = (left + right) * lr;
5049 out[13] = (top + bottom) * bt;
5050 out[14] = (far + near) * nf;
5051 out[15] = 1;
5052 return out;
5053};
5054
5055/**
5056 * Generates a look-at matrix with the given eye position, focal point, and up axis
5057 *
5058 * @param {mat4} out mat4 frustum matrix will be written into
5059 * @param {vec3} eye Position of the viewer
5060 * @param {vec3} center Point the viewer is looking at
5061 * @param {vec3} up vec3 pointing up
5062 * @returns {mat4} out
5063 */
5064mat4.lookAt = function (out, eye, center, up) {
5065 var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
5066 eyex = eye[0],
5067 eyey = eye[1],
5068 eyez = eye[2],
5069 upx = up[0],
5070 upy = up[1],
5071 upz = up[2],
5072 centerx = center[0],
5073 centery = center[1],
5074 centerz = center[2];
5075
5076 if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
5077 Math.abs(eyey - centery) < GLMAT_EPSILON &&
5078 Math.abs(eyez - centerz) < GLMAT_EPSILON) {
5079 return mat4.identity(out);
5080 }
5081
5082 z0 = eyex - centerx;
5083 z1 = eyey - centery;
5084 z2 = eyez - centerz;
5085
5086 len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
5087 z0 *= len;
5088 z1 *= len;
5089 z2 *= len;
5090
5091 x0 = upy * z2 - upz * z1;
5092 x1 = upz * z0 - upx * z2;
5093 x2 = upx * z1 - upy * z0;
5094 len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
5095 if (!len) {
5096 x0 = 0;
5097 x1 = 0;
5098 x2 = 0;
5099 } else {
5100 len = 1 / len;
5101 x0 *= len;
5102 x1 *= len;
5103 x2 *= len;
5104 }
5105
5106 y0 = z1 * x2 - z2 * x1;
5107 y1 = z2 * x0 - z0 * x2;
5108 y2 = z0 * x1 - z1 * x0;
5109
5110 len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
5111 if (!len) {
5112 y0 = 0;
5113 y1 = 0;
5114 y2 = 0;
5115 } else {
5116 len = 1 / len;
5117 y0 *= len;
5118 y1 *= len;
5119 y2 *= len;
5120 }
5121
5122 out[0] = x0;
5123 out[1] = y0;
5124 out[2] = z0;
5125 out[3] = 0;
5126 out[4] = x1;
5127 out[5] = y1;
5128 out[6] = z1;
5129 out[7] = 0;
5130 out[8] = x2;
5131 out[9] = y2;
5132 out[10] = z2;
5133 out[11] = 0;
5134 out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
5135 out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
5136 out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
5137 out[15] = 1;
5138
5139 return out;
5140};
5141
5142/**
5143 * Returns a string representation of a mat4
5144 *
5145 * @param {mat4} mat matrix to represent as a string
5146 * @returns {String} string representation of the matrix
5147 */
5148mat4.str = function (a) {
5149 return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
5150 a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
5151 a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
5152 a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
5153};
5154
5155if(typeof(exports) !== 'undefined') {
5156 exports.mat4 = mat4;
5157}
5158;
5159/* Copyright (c) 2012, Brandon Jones, Colin MacKenzie IV. All rights reserved.
5160
5161Redistribution and use in source and binary forms, with or without modification,
5162are permitted provided that the following conditions are met:
5163
5164 * Redistributions of source code must retain the above copyright notice, this
5165 list of conditions and the following disclaimer.
5166 * Redistributions in binary form must reproduce the above copyright notice,
5167 this list of conditions and the following disclaimer in the documentation
5168 and/or other materials provided with the distribution.
5169
5170THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
5171ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
5172WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
5173DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
5174ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
5175(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
5176LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
5177ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5178(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5179SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
5180
5181/**
5182 * @class Quaternion
5183 * @name quat
5184 */
5185
5186var quat = {};
5187
5188var quatIdentity = new Float32Array([0, 0, 0, 1]);
5189
5190if(!GLMAT_EPSILON) {
5191 var GLMAT_EPSILON = 0.000001;
5192}
5193
5194/**
5195 * Creates a new identity quat
5196 *
5197 * @returns {quat} a new quaternion
5198 */
5199quat.create = function() {
5200 return new Float32Array(quatIdentity);
5201};
5202
5203/**
5204 * Creates a new quat initialized with values from an existing quaternion
5205 *
5206 * @param {quat} a quaternion to clone
5207 * @returns {quat} a new quaternion
5208 */
5209quat.clone = vec4.clone;
5210
5211/**
5212 * Creates a new quat initialized with the given values
5213 *
5214 * @param {Number} x X component
5215 * @param {Number} y Y component
5216 * @param {Number} z Z component
5217 * @param {Number} w W component
5218 * @returns {quat} a new quaternion
5219 */
5220quat.fromValues = vec4.fromValues;
5221
5222/**
5223 * Copy the values from one quat to another
5224 *
5225 * @param {quat} out the receiving quaternion
5226 * @param {quat} a the source quaternion
5227 * @returns {quat} out
5228 */
5229quat.copy = vec4.copy;
5230
5231/**
5232 * Set the components of a quat to the given values
5233 *
5234 * @param {quat} out the receiving quaternion
5235 * @param {Number} x X component
5236 * @param {Number} y Y component
5237 * @param {Number} z Z component
5238 * @param {Number} w W component
5239 * @returns {quat} out
5240 */
5241quat.set = vec4.set;
5242
5243/**
5244 * Set a quat to the identity quaternion
5245 *
5246 * @param {quat} out the receiving quaternion
5247 * @returns {quat} out
5248 */
5249quat.identity = function(out) {
5250 out[0] = 0;
5251 out[1] = 0;
5252 out[2] = 0;
5253 out[3] = 1;
5254 return out;
5255};
5256
5257/**
5258 * Sets a quat from the given angle and rotation axis,
5259 * then returns it.
5260 *
5261 * @param {quat} out the receiving quaternion
5262 * @param {vec3} axis the axis around which to rotate
5263 * @param {Number} rad the angle in radians
5264 * @returns {quat} out
5265 **/
5266quat.setAxisAngle = function(out, axis, rad) {
5267 rad = rad * 0.5;
5268 var s = Math.sin(rad);
5269 out[0] = s * axis[0];
5270 out[1] = s * axis[1];
5271 out[2] = s * axis[2];
5272 out[3] = Math.cos(rad);
5273 return out;
5274};
5275
5276/**
5277 * Adds two quat's
5278 *
5279 * @param {quat} out the receiving quaternion
5280 * @param {quat} a the first operand
5281 * @param {quat} b the second operand
5282 * @returns {quat} out
5283 */
5284quat.add = vec4.add;
5285
5286/**
5287 * Multiplies two quat's
5288 *
5289 * @param {quat} out the receiving quaternion
5290 * @param {quat} a the first operand
5291 * @param {quat} b the second operand
5292 * @returns {quat} out
5293 */
5294quat.mul = quat.multiply = function(out, a, b) {
5295 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
5296 bx = b[0], by = b[1], bz = b[2], bw = b[3];
5297
5298 out[0] = ax * bw + aw * bx + ay * bz - az * by;
5299 out[1] = ay * bw + aw * by + az * bx - ax * bz;
5300 out[2] = az * bw + aw * bz + ax * by - ay * bx;
5301 out[3] = aw * bw - ax * bx - ay * by - az * bz;
5302 return out;
5303};
5304
5305/**
5306 * Scales a quat by a scalar number
5307 *
5308 * @param {quat} out the receiving vector
5309 * @param {quat} a the vector to scale
5310 * @param {quat} b amount to scale the vector by
5311 * @returns {quat} out
5312 */
5313quat.scale = vec4.scale;
5314
5315/**
5316 * Rotates a quaternion by the given angle around the X axis
5317 *
5318 * @param {quat} out quat receiving operation result
5319 * @param {quat} a quat to rotate
5320 * @param {number} rad angle (in radians) to rotate
5321 * @returns {quat} out
5322 */
5323quat.rotateX = function (out, a, rad) {
5324 rad *= 0.5;
5325
5326 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
5327 bx = Math.sin(rad), bw = Math.cos(rad);
5328
5329 out[0] = ax * bw + aw * bx;
5330 out[1] = ay * bw + az * bx;
5331 out[2] = az * bw - ay * bx;
5332 out[3] = aw * bw - ax * bx;
5333 return out;
5334};
5335
5336/**
5337 * Rotates a quaternion by the given angle around the X axis
5338 *
5339 * @param {quat} out quat receiving operation result
5340 * @param {quat} a quat to rotate
5341 * @param {number} rad angle (in radians) to rotate
5342 * @returns {quat} out
5343 */
5344quat.rotateY = function (out, a, rad) {
5345 rad *= 0.5;
5346
5347 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
5348 by = Math.sin(rad), bw = Math.cos(rad);
5349
5350 out[0] = ax * bw - az * by;
5351 out[1] = ay * bw + aw * by;
5352 out[2] = az * bw + ax * by;
5353 out[3] = aw * bw - ay * by;
5354 return out;
5355};
5356
5357/**
5358 * Rotates a quaternion by the given angle around the X axis
5359 *
5360 * @param {quat} out quat receiving operation result
5361 * @param {quat} a quat to rotate
5362 * @param {number} rad angle (in radians) to rotate
5363 * @returns {quat} out
5364 */
5365quat.rotateZ = function (out, a, rad) {
5366 rad *= 0.5;
5367
5368 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
5369 bz = Math.sin(rad), bw = Math.cos(rad);
5370
5371 out[0] = ax * bw + ay * bz;
5372 out[1] = ay * bw - ax * bz;
5373 out[2] = az * bw + aw * bz;
5374 out[3] = aw * bw - az * bz;
5375 return out;
5376};
5377
5378/**
5379 * Calculates the W component of a quat from the X, Y, and Z components.
5380 * Assumes that quaternion is 1 unit in length.
5381 * Any existing W component will be ignored.
5382 *
5383 * @param {quat} out the receiving quaternion
5384 * @param {quat} a quat to calculate W component of
5385 * @returns {quat} out
5386 */
5387quat.calculateW = function (out, a) {
5388 var x = a[0], y = a[1], z = a[2];
5389
5390 out[0] = x;
5391 out[1] = y;
5392 out[2] = z;
5393 out[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
5394 return out;
5395};
5396
5397/**
5398 * Caclulates the dot product of two quat's
5399 *
5400 * @param {quat} a the first operand
5401 * @param {quat} b the second operand
5402 * @returns {Number} dot product of a and b
5403 */
5404quat.dot = vec4.dot;
5405
5406/**
5407 * Performs a linear interpolation between two quat's
5408 *
5409 * @param {quat} out the receiving quaternion
5410 * @param {quat} a the first operand
5411 * @param {quat} b the second operand
5412 * @param {Number} t interpolation amount between the two inputs
5413 * @returns {quat} out
5414 */
5415quat.lerp = vec4.lerp;
5416
5417/**
5418 * Performs a spherical linear interpolation between two quat
5419 *
5420 * @param {quat} out the receiving quaternion
5421 * @param {quat} a the first operand
5422 * @param {quat} b the second operand
5423 * @param {Number} t interpolation amount between the two inputs
5424 * @returns {quat} out
5425 */
5426quat.slerp = function (out, a, b, t) {
5427 var ax = a[0], ay = a[1], az = a[2], aw = a[3],
5428 bx = b[0], by = b[1], bz = b[2], bw = a[3];
5429
5430 var cosHalfTheta = ax * bx + ay * by + az * bz + aw * bw,
5431 halfTheta,
5432 sinHalfTheta,
5433 ratioA,
5434 ratioB;
5435
5436 if (Math.abs(cosHalfTheta) >= 1.0) {
5437 if (out !== a) {
5438 out[0] = ax;
5439 out[1] = ay;
5440 out[2] = az;
5441 out[3] = aw;
5442 }
5443 return out;
5444 }
5445
5446 halfTheta = Math.acos(cosHalfTheta);
5447 sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
5448
5449 if (Math.abs(sinHalfTheta) < 0.001) {
5450 out[0] = (ax * 0.5 + bx * 0.5);
5451 out[1] = (ay * 0.5 + by * 0.5);
5452 out[2] = (az * 0.5 + bz * 0.5);
5453 out[3] = (aw * 0.5 + bw * 0.5);
5454 return out;
5455 }
5456
5457 ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta;
5458 ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
5459
5460 out[0] = (ax * ratioA + bx * ratioB);
5461 out[1] = (ay * ratioA + by * ratioB);
5462 out[2] = (az * ratioA + bz * ratioB);
5463 out[3] = (aw * ratioA + bw * ratioB);
5464
5465 return out;
5466};
5467
5468/**
5469 * Calculates the inverse of a quat
5470 *
5471 * @param {quat} out the receiving quaternion
5472 * @param {quat} a quat to calculate inverse of
5473 * @returns {quat} out
5474 */
5475quat.invert = function(out, a) {
5476 var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
5477 dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
5478 invDot = dot ? 1.0/dot : 0;
5479
5480 // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
5481
5482 out[0] = -a0*invDot;
5483 out[1] = -a1*invDot;
5484 out[2] = -a2*invDot;
5485 out[3] = a3*invDot;
5486 return out;
5487};
5488
5489/**
5490 * Calculates the conjugate of a quat
5491 * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
5492 *
5493 * @param {quat} out the receiving quaternion
5494 * @param {quat} a quat to calculate conjugate of
5495 * @returns {quat} out
5496 */
5497quat.conjugate = function (out, a) {
5498 out[0] = -a[0];
5499 out[1] = -a[1];
5500 out[2] = -a[2];
5501 out[3] = a[3];
5502 return out;
5503};
5504
5505/**
5506 * Caclulates the length of a quat
5507 *
5508 * @param {quat} a vector to calculate length of
5509 * @returns {Number} length of a
5510 */
5511quat.len = quat.length = vec4.length;
5512
5513/**
5514 * Caclulates the squared length of a quat
5515 *
5516 * @param {quat} a vector to calculate squared length of
5517 * @returns {Number} squared length of a
5518 */
5519quat.sqrLen = quat.squaredLength = vec4.squaredLength;
5520
5521/**
5522 * Normalize a quat
5523 *
5524 * @param {quat} out the receiving quaternion
5525 * @param {quat} a quaternion to normalize
5526 * @returns {quat} out
5527 */
5528quat.normalize = vec4.normalize;
5529
5530/**
5531 * Returns a string representation of a quatenion
5532 *
5533 * @param {quat} vec vector to represent as a string
5534 * @returns {String} string representation of the vector
5535 */
5536quat.str = function (a) {
5537 return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
5538};
5539
5540if(typeof(exports) !== 'undefined') {
5541 exports.quat = quat;
5542}
5543;
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554 })(shim.exports);
5555})();
5556
5557})()
5558},{}],20:[function(require,module,exports){
5559(function(){// Underscore.js 1.4.4
5560// http://underscorejs.org
5561// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
5562// Underscore may be freely distributed under the MIT license.
5563
5564(function() {
5565
5566 // Baseline setup
5567 // --------------
5568
5569 // Establish the root object, `window` in the browser, or `global` on the server.
5570 var root = this;
5571
5572 // Save the previous value of the `_` variable.
5573 var previousUnderscore = root._;
5574
5575 // Establish the object that gets returned to break out of a loop iteration.
5576 var breaker = {};
5577
5578 // Save bytes in the minified (but not gzipped) version:
5579 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
5580
5581 // Create quick reference variables for speed access to core prototypes.
5582 var push = ArrayProto.push,
5583 slice = ArrayProto.slice,
5584 concat = ArrayProto.concat,
5585 toString = ObjProto.toString,
5586 hasOwnProperty = ObjProto.hasOwnProperty;
5587
5588 // All **ECMAScript 5** native function implementations that we hope to use
5589 // are declared here.
5590 var
5591 nativeForEach = ArrayProto.forEach,
5592 nativeMap = ArrayProto.map,
5593 nativeReduce = ArrayProto.reduce,
5594 nativeReduceRight = ArrayProto.reduceRight,
5595 nativeFilter = ArrayProto.filter,
5596 nativeEvery = ArrayProto.every,
5597 nativeSome = ArrayProto.some,
5598 nativeIndexOf = ArrayProto.indexOf,
5599 nativeLastIndexOf = ArrayProto.lastIndexOf,
5600 nativeIsArray = Array.isArray,
5601 nativeKeys = Object.keys,
5602 nativeBind = FuncProto.bind;
5603
5604 // Create a safe reference to the Underscore object for use below.
5605 var _ = function(obj) {
5606 if (obj instanceof _) return obj;
5607 if (!(this instanceof _)) return new _(obj);
5608 this._wrapped = obj;
5609 };
5610
5611 // Export the Underscore object for **Node.js**, with
5612 // backwards-compatibility for the old `require()` API. If we're in
5613 // the browser, add `_` as a global object via a string identifier,
5614 // for Closure Compiler "advanced" mode.
5615 if (typeof exports !== 'undefined') {
5616 if (typeof module !== 'undefined' && module.exports) {
5617 exports = module.exports = _;
5618 }
5619 exports._ = _;
5620 } else {
5621 root._ = _;
5622 }
5623
5624 // Current version.
5625 _.VERSION = '1.4.4';
5626
5627 // Collection Functions
5628 // --------------------
5629
5630 // The cornerstone, an `each` implementation, aka `forEach`.
5631 // Handles objects with the built-in `forEach`, arrays, and raw objects.
5632 // Delegates to **ECMAScript 5**'s native `forEach` if available.
5633 var each = _.each = _.forEach = function(obj, iterator, context) {
5634 if (obj == null) return;
5635 if (nativeForEach && obj.forEach === nativeForEach) {
5636 obj.forEach(iterator, context);
5637 } else if (obj.length === +obj.length) {
5638 for (var i = 0, l = obj.length; i < l; i++) {
5639 if (iterator.call(context, obj[i], i, obj) === breaker) return;
5640 }
5641 } else {
5642 for (var key in obj) {
5643 if (_.has(obj, key)) {
5644 if (iterator.call(context, obj[key], key, obj) === breaker) return;
5645 }
5646 }
5647 }
5648 };
5649
5650 // Return the results of applying the iterator to each element.
5651 // Delegates to **ECMAScript 5**'s native `map` if available.
5652 _.map = _.collect = function(obj, iterator, context) {
5653 var results = [];
5654 if (obj == null) return results;
5655 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
5656 each(obj, function(value, index, list) {
5657 results[results.length] = iterator.call(context, value, index, list);
5658 });
5659 return results;
5660 };
5661
5662 var reduceError = 'Reduce of empty array with no initial value';
5663
5664 // **Reduce** builds up a single result from a list of values, aka `inject`,
5665 // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
5666 _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
5667 var initial = arguments.length > 2;
5668 if (obj == null) obj = [];
5669 if (nativeReduce && obj.reduce === nativeReduce) {
5670 if (context) iterator = _.bind(iterator, context);
5671 return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
5672 }
5673 each(obj, function(value, index, list) {
5674 if (!initial) {
5675 memo = value;
5676 initial = true;
5677 } else {
5678 memo = iterator.call(context, memo, value, index, list);
5679 }
5680 });
5681 if (!initial) throw new TypeError(reduceError);
5682 return memo;
5683 };
5684
5685 // The right-associative version of reduce, also known as `foldr`.
5686 // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
5687 _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
5688 var initial = arguments.length > 2;
5689 if (obj == null) obj = [];
5690 if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
5691 if (context) iterator = _.bind(iterator, context);
5692 return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
5693 }
5694 var length = obj.length;
5695 if (length !== +length) {
5696 var keys = _.keys(obj);
5697 length = keys.length;
5698 }
5699 each(obj, function(value, index, list) {
5700 index = keys ? keys[--length] : --length;
5701 if (!initial) {
5702 memo = obj[index];
5703 initial = true;
5704 } else {
5705 memo = iterator.call(context, memo, obj[index], index, list);
5706 }
5707 });
5708 if (!initial) throw new TypeError(reduceError);
5709 return memo;
5710 };
5711
5712 // Return the first value which passes a truth test. Aliased as `detect`.
5713 _.find = _.detect = function(obj, iterator, context) {
5714 var result;
5715 any(obj, function(value, index, list) {
5716 if (iterator.call(context, value, index, list)) {
5717 result = value;
5718 return true;
5719 }
5720 });
5721 return result;
5722 };
5723
5724 // Return all the elements that pass a truth test.
5725 // Delegates to **ECMAScript 5**'s native `filter` if available.
5726 // Aliased as `select`.
5727 _.filter = _.select = function(obj, iterator, context) {
5728 var results = [];
5729 if (obj == null) return results;
5730 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
5731 each(obj, function(value, index, list) {
5732 if (iterator.call(context, value, index, list)) results[results.length] = value;
5733 });
5734 return results;
5735 };
5736
5737 // Return all the elements for which a truth test fails.
5738 _.reject = function(obj, iterator, context) {
5739 return _.filter(obj, function(value, index, list) {
5740 return !iterator.call(context, value, index, list);
5741 }, context);
5742 };
5743
5744 // Determine whether all of the elements match a truth test.
5745 // Delegates to **ECMAScript 5**'s native `every` if available.
5746 // Aliased as `all`.
5747 _.every = _.all = function(obj, iterator, context) {
5748 iterator || (iterator = _.identity);
5749 var result = true;
5750 if (obj == null) return result;
5751 if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
5752 each(obj, function(value, index, list) {
5753 if (!(result = result && iterator.call(context, value, index, list))) return breaker;
5754 });
5755 return !!result;
5756 };
5757
5758 // Determine if at least one element in the object matches a truth test.
5759 // Delegates to **ECMAScript 5**'s native `some` if available.
5760 // Aliased as `any`.
5761 var any = _.some = _.any = function(obj, iterator, context) {
5762 iterator || (iterator = _.identity);
5763 var result = false;
5764 if (obj == null) return result;
5765 if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
5766 each(obj, function(value, index, list) {
5767 if (result || (result = iterator.call(context, value, index, list))) return breaker;
5768 });
5769 return !!result;
5770 };
5771
5772 // Determine if the array or object contains a given value (using `===`).
5773 // Aliased as `include`.
5774 _.contains = _.include = function(obj, target) {
5775 if (obj == null) return false;
5776 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
5777 return any(obj, function(value) {
5778 return value === target;
5779 });
5780 };
5781
5782 // Invoke a method (with arguments) on every item in a collection.
5783 _.invoke = function(obj, method) {
5784 var args = slice.call(arguments, 2);
5785 var isFunc = _.isFunction(method);
5786 return _.map(obj, function(value) {
5787 return (isFunc ? method : value[method]).apply(value, args);
5788 });
5789 };
5790
5791 // Convenience version of a common use case of `map`: fetching a property.
5792 _.pluck = function(obj, key) {
5793 return _.map(obj, function(value){ return value[key]; });
5794 };
5795
5796 // Convenience version of a common use case of `filter`: selecting only objects
5797 // containing specific `key:value` pairs.
5798 _.where = function(obj, attrs, first) {
5799 if (_.isEmpty(attrs)) return first ? null : [];
5800 return _[first ? 'find' : 'filter'](obj, function(value) {
5801 for (var key in attrs) {
5802 if (attrs[key] !== value[key]) return false;
5803 }
5804 return true;
5805 });
5806 };
5807
5808 // Convenience version of a common use case of `find`: getting the first object
5809 // containing specific `key:value` pairs.
5810 _.findWhere = function(obj, attrs) {
5811 return _.where(obj, attrs, true);
5812 };
5813
5814 // Return the maximum element or (element-based computation).
5815 // Can't optimize arrays of integers longer than 65,535 elements.
5816 // See: https://bugs.webkit.org/show_bug.cgi?id=80797
5817 _.max = function(obj, iterator, context) {
5818 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
5819 return Math.max.apply(Math, obj);
5820 }
5821 if (!iterator && _.isEmpty(obj)) return -Infinity;
5822 var result = {computed : -Infinity, value: -Infinity};
5823 each(obj, function(value, index, list) {
5824 var computed = iterator ? iterator.call(context, value, index, list) : value;
5825 computed >= result.computed && (result = {value : value, computed : computed});
5826 });
5827 return result.value;
5828 };
5829
5830 // Return the minimum element (or element-based computation).
5831 _.min = function(obj, iterator, context) {
5832 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
5833 return Math.min.apply(Math, obj);
5834 }
5835 if (!iterator && _.isEmpty(obj)) return Infinity;
5836 var result = {computed : Infinity, value: Infinity};
5837 each(obj, function(value, index, list) {
5838 var computed = iterator ? iterator.call(context, value, index, list) : value;
5839 computed < result.computed && (result = {value : value, computed : computed});
5840 });
5841 return result.value;
5842 };
5843
5844 // Shuffle an array.
5845 _.shuffle = function(obj) {
5846 var rand;
5847 var index = 0;
5848 var shuffled = [];
5849 each(obj, function(value) {
5850 rand = _.random(index++);
5851 shuffled[index - 1] = shuffled[rand];
5852 shuffled[rand] = value;
5853 });
5854 return shuffled;
5855 };
5856
5857 // An internal function to generate lookup iterators.
5858 var lookupIterator = function(value) {
5859 return _.isFunction(value) ? value : function(obj){ return obj[value]; };
5860 };
5861
5862 // Sort the object's values by a criterion produced by an iterator.
5863 _.sortBy = function(obj, value, context) {
5864 var iterator = lookupIterator(value);
5865 return _.pluck(_.map(obj, function(value, index, list) {
5866 return {
5867 value : value,
5868 index : index,
5869 criteria : iterator.call(context, value, index, list)
5870 };
5871 }).sort(function(left, right) {
5872 var a = left.criteria;
5873 var b = right.criteria;
5874 if (a !== b) {
5875 if (a > b || a === void 0) return 1;
5876 if (a < b || b === void 0) return -1;
5877 }
5878 return left.index < right.index ? -1 : 1;
5879 }), 'value');
5880 };
5881
5882 // An internal function used for aggregate "group by" operations.
5883 var group = function(obj, value, context, behavior) {
5884 var result = {};
5885 var iterator = lookupIterator(value || _.identity);
5886 each(obj, function(value, index) {
5887 var key = iterator.call(context, value, index, obj);
5888 behavior(result, key, value);
5889 });
5890 return result;
5891 };
5892
5893 // Groups the object's values by a criterion. Pass either a string attribute
5894 // to group by, or a function that returns the criterion.
5895 _.groupBy = function(obj, value, context) {
5896 return group(obj, value, context, function(result, key, value) {
5897 (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
5898 });
5899 };
5900
5901 // Counts instances of an object that group by a certain criterion. Pass
5902 // either a string attribute to count by, or a function that returns the
5903 // criterion.
5904 _.countBy = function(obj, value, context) {
5905 return group(obj, value, context, function(result, key) {
5906 if (!_.has(result, key)) result[key] = 0;
5907 result[key]++;
5908 });
5909 };
5910
5911 // Use a comparator function to figure out the smallest index at which
5912 // an object should be inserted so as to maintain order. Uses binary search.
5913 _.sortedIndex = function(array, obj, iterator, context) {
5914 iterator = iterator == null ? _.identity : lookupIterator(iterator);
5915 var value = iterator.call(context, obj);
5916 var low = 0, high = array.length;
5917 while (low < high) {
5918 var mid = (low + high) >>> 1;
5919 iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
5920 }
5921 return low;
5922 };
5923
5924 // Safely convert anything iterable into a real, live array.
5925 _.toArray = function(obj) {
5926 if (!obj) return [];
5927 if (_.isArray(obj)) return slice.call(obj);
5928 if (obj.length === +obj.length) return _.map(obj, _.identity);
5929 return _.values(obj);
5930 };
5931
5932 // Return the number of elements in an object.
5933 _.size = function(obj) {
5934 if (obj == null) return 0;
5935 return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
5936 };
5937
5938 // Array Functions
5939 // ---------------
5940
5941 // Get the first element of an array. Passing **n** will return the first N
5942 // values in the array. Aliased as `head` and `take`. The **guard** check
5943 // allows it to work with `_.map`.
5944 _.first = _.head = _.take = function(array, n, guard) {
5945 if (array == null) return void 0;
5946 return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
5947 };
5948
5949 // Returns everything but the last entry of the array. Especially useful on
5950 // the arguments object. Passing **n** will return all the values in
5951 // the array, excluding the last N. The **guard** check allows it to work with
5952 // `_.map`.
5953 _.initial = function(array, n, guard) {
5954 return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
5955 };
5956
5957 // Get the last element of an array. Passing **n** will return the last N
5958 // values in the array. The **guard** check allows it to work with `_.map`.
5959 _.last = function(array, n, guard) {
5960 if (array == null) return void 0;
5961 if ((n != null) && !guard) {
5962 return slice.call(array, Math.max(array.length - n, 0));
5963 } else {
5964 return array[array.length - 1];
5965 }
5966 };
5967
5968 // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
5969 // Especially useful on the arguments object. Passing an **n** will return
5970 // the rest N values in the array. The **guard**
5971 // check allows it to work with `_.map`.
5972 _.rest = _.tail = _.drop = function(array, n, guard) {
5973 return slice.call(array, (n == null) || guard ? 1 : n);
5974 };
5975
5976 // Trim out all falsy values from an array.
5977 _.compact = function(array) {
5978 return _.filter(array, _.identity);
5979 };
5980
5981 // Internal implementation of a recursive `flatten` function.
5982 var flatten = function(input, shallow, output) {
5983 each(input, function(value) {
5984 if (_.isArray(value)) {
5985 shallow ? push.apply(output, value) : flatten(value, shallow, output);
5986 } else {
5987 output.push(value);
5988 }
5989 });
5990 return output;
5991 };
5992
5993 // Return a completely flattened version of an array.
5994 _.flatten = function(array, shallow) {
5995 return flatten(array, shallow, []);
5996 };
5997
5998 // Return a version of the array that does not contain the specified value(s).
5999 _.without = function(array) {
6000 return _.difference(array, slice.call(arguments, 1));
6001 };
6002
6003 // Produce a duplicate-free version of the array. If the array has already
6004 // been sorted, you have the option of using a faster algorithm.
6005 // Aliased as `unique`.
6006 _.uniq = _.unique = function(array, isSorted, iterator, context) {
6007 if (_.isFunction(isSorted)) {
6008 context = iterator;
6009 iterator = isSorted;
6010 isSorted = false;
6011 }
6012 var initial = iterator ? _.map(array, iterator, context) : array;
6013 var results = [];
6014 var seen = [];
6015 each(initial, function(value, index) {
6016 if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
6017 seen.push(value);
6018 results.push(array[index]);
6019 }
6020 });
6021 return results;
6022 };
6023
6024 // Produce an array that contains the union: each distinct element from all of
6025 // the passed-in arrays.
6026 _.union = function() {
6027 return _.uniq(concat.apply(ArrayProto, arguments));
6028 };
6029
6030 // Produce an array that contains every item shared between all the
6031 // passed-in arrays.
6032 _.intersection = function(array) {
6033 var rest = slice.call(arguments, 1);
6034 return _.filter(_.uniq(array), function(item) {
6035 return _.every(rest, function(other) {
6036 return _.indexOf(other, item) >= 0;
6037 });
6038 });
6039 };
6040
6041 // Take the difference between one array and a number of other arrays.
6042 // Only the elements present in just the first array will remain.
6043 _.difference = function(array) {
6044 var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
6045 return _.filter(array, function(value){ return !_.contains(rest, value); });
6046 };
6047
6048 // Zip together multiple lists into a single array -- elements that share
6049 // an index go together.
6050 _.zip = function() {
6051 var args = slice.call(arguments);
6052 var length = _.max(_.pluck(args, 'length'));
6053 var results = new Array(length);
6054 for (var i = 0; i < length; i++) {
6055 results[i] = _.pluck(args, "" + i);
6056 }
6057 return results;
6058 };
6059
6060 // Converts lists into objects. Pass either a single array of `[key, value]`
6061 // pairs, or two parallel arrays of the same length -- one of keys, and one of
6062 // the corresponding values.
6063 _.object = function(list, values) {
6064 if (list == null) return {};
6065 var result = {};
6066 for (var i = 0, l = list.length; i < l; i++) {
6067 if (values) {
6068 result[list[i]] = values[i];
6069 } else {
6070 result[list[i][0]] = list[i][1];
6071 }
6072 }
6073 return result;
6074 };
6075
6076 // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
6077 // we need this function. Return the position of the first occurrence of an
6078 // item in an array, or -1 if the item is not included in the array.
6079 // Delegates to **ECMAScript 5**'s native `indexOf` if available.
6080 // If the array is large and already in sort order, pass `true`
6081 // for **isSorted** to use binary search.
6082 _.indexOf = function(array, item, isSorted) {
6083 if (array == null) return -1;
6084 var i = 0, l = array.length;
6085 if (isSorted) {
6086 if (typeof isSorted == 'number') {
6087 i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
6088 } else {
6089 i = _.sortedIndex(array, item);
6090 return array[i] === item ? i : -1;
6091 }
6092 }
6093 if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
6094 for (; i < l; i++) if (array[i] === item) return i;
6095 return -1;
6096 };
6097
6098 // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
6099 _.lastIndexOf = function(array, item, from) {
6100 if (array == null) return -1;
6101 var hasIndex = from != null;
6102 if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
6103 return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
6104 }
6105 var i = (hasIndex ? from : array.length);
6106 while (i--) if (array[i] === item) return i;
6107 return -1;
6108 };
6109
6110 // Generate an integer Array containing an arithmetic progression. A port of
6111 // the native Python `range()` function. See
6112 // [the Python documentation](http://docs.python.org/library/functions.html#range).
6113 _.range = function(start, stop, step) {
6114 if (arguments.length <= 1) {
6115 stop = start || 0;
6116 start = 0;
6117 }
6118 step = arguments[2] || 1;
6119
6120 var len = Math.max(Math.ceil((stop - start) / step), 0);
6121 var idx = 0;
6122 var range = new Array(len);
6123
6124 while(idx < len) {
6125 range[idx++] = start;
6126 start += step;
6127 }
6128
6129 return range;
6130 };
6131
6132 // Function (ahem) Functions
6133 // ------------------
6134
6135 // Create a function bound to a given object (assigning `this`, and arguments,
6136 // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
6137 // available.
6138 _.bind = function(func, context) {
6139 if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
6140 var args = slice.call(arguments, 2);
6141 return function() {
6142 return func.apply(context, args.concat(slice.call(arguments)));
6143 };
6144 };
6145
6146 // Partially apply a function by creating a version that has had some of its
6147 // arguments pre-filled, without changing its dynamic `this` context.
6148 _.partial = function(func) {
6149 var args = slice.call(arguments, 1);
6150 return function() {
6151 return func.apply(this, args.concat(slice.call(arguments)));
6152 };
6153 };
6154
6155 // Bind all of an object's methods to that object. Useful for ensuring that
6156 // all callbacks defined on an object belong to it.
6157 _.bindAll = function(obj) {
6158 var funcs = slice.call(arguments, 1);
6159 if (funcs.length === 0) funcs = _.functions(obj);
6160 each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
6161 return obj;
6162 };
6163
6164 // Memoize an expensive function by storing its results.
6165 _.memoize = function(func, hasher) {
6166 var memo = {};
6167 hasher || (hasher = _.identity);
6168 return function() {
6169 var key = hasher.apply(this, arguments);
6170 return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
6171 };
6172 };
6173
6174 // Delays a function for the given number of milliseconds, and then calls
6175 // it with the arguments supplied.
6176 _.delay = function(func, wait) {
6177 var args = slice.call(arguments, 2);
6178 return setTimeout(function(){ return func.apply(null, args); }, wait);
6179 };
6180
6181 // Defers a function, scheduling it to run after the current call stack has
6182 // cleared.
6183 _.defer = function(func) {
6184 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
6185 };
6186
6187 // Returns a function, that, when invoked, will only be triggered at most once
6188 // during a given window of time.
6189 _.throttle = function(func, wait) {
6190 var context, args, timeout, result;
6191 var previous = 0;
6192 var later = function() {
6193 previous = new Date;
6194 timeout = null;
6195 result = func.apply(context, args);
6196 };
6197 return function() {
6198 var now = new Date;
6199 var remaining = wait - (now - previous);
6200 context = this;
6201 args = arguments;
6202 if (remaining <= 0) {
6203 clearTimeout(timeout);
6204 timeout = null;
6205 previous = now;
6206 result = func.apply(context, args);
6207 } else if (!timeout) {
6208 timeout = setTimeout(later, remaining);
6209 }
6210 return result;
6211 };
6212 };
6213
6214 // Returns a function, that, as long as it continues to be invoked, will not
6215 // be triggered. The function will be called after it stops being called for
6216 // N milliseconds. If `immediate` is passed, trigger the function on the
6217 // leading edge, instead of the trailing.
6218 _.debounce = function(func, wait, immediate) {
6219 var timeout, result;
6220 return function() {
6221 var context = this, args = arguments;
6222 var later = function() {
6223 timeout = null;
6224 if (!immediate) result = func.apply(context, args);
6225 };
6226 var callNow = immediate && !timeout;
6227 clearTimeout(timeout);
6228 timeout = setTimeout(later, wait);
6229 if (callNow) result = func.apply(context, args);
6230 return result;
6231 };
6232 };
6233
6234 // Returns a function that will be executed at most one time, no matter how
6235 // often you call it. Useful for lazy initialization.
6236 _.once = function(func) {
6237 var ran = false, memo;
6238 return function() {
6239 if (ran) return memo;
6240 ran = true;
6241 memo = func.apply(this, arguments);
6242 func = null;
6243 return memo;
6244 };
6245 };
6246
6247 // Returns the first function passed as an argument to the second,
6248 // allowing you to adjust arguments, run code before and after, and
6249 // conditionally execute the original function.
6250 _.wrap = function(func, wrapper) {
6251 return function() {
6252 var args = [func];
6253 push.apply(args, arguments);
6254 return wrapper.apply(this, args);
6255 };
6256 };
6257
6258 // Returns a function that is the composition of a list of functions, each
6259 // consuming the return value of the function that follows.
6260 _.compose = function() {
6261 var funcs = arguments;
6262 return function() {
6263 var args = arguments;
6264 for (var i = funcs.length - 1; i >= 0; i--) {
6265 args = [funcs[i].apply(this, args)];
6266 }
6267 return args[0];
6268 };
6269 };
6270
6271 // Returns a function that will only be executed after being called N times.
6272 _.after = function(times, func) {
6273 if (times <= 0) return func();
6274 return function() {
6275 if (--times < 1) {
6276 return func.apply(this, arguments);
6277 }
6278 };
6279 };
6280
6281 // Object Functions
6282 // ----------------
6283
6284 // Retrieve the names of an object's properties.
6285 // Delegates to **ECMAScript 5**'s native `Object.keys`
6286 _.keys = nativeKeys || function(obj) {
6287 if (obj !== Object(obj)) throw new TypeError('Invalid object');
6288 var keys = [];
6289 for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
6290 return keys;
6291 };
6292
6293 // Retrieve the values of an object's properties.
6294 _.values = function(obj) {
6295 var values = [];
6296 for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
6297 return values;
6298 };
6299
6300 // Convert an object into a list of `[key, value]` pairs.
6301 _.pairs = function(obj) {
6302 var pairs = [];
6303 for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
6304 return pairs;
6305 };
6306
6307 // Invert the keys and values of an object. The values must be serializable.
6308 _.invert = function(obj) {
6309 var result = {};
6310 for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
6311 return result;
6312 };
6313
6314 // Return a sorted list of the function names available on the object.
6315 // Aliased as `methods`
6316 _.functions = _.methods = function(obj) {
6317 var names = [];
6318 for (var key in obj) {
6319 if (_.isFunction(obj[key])) names.push(key);
6320 }
6321 return names.sort();
6322 };
6323
6324 // Extend a given object with all the properties in passed-in object(s).
6325 _.extend = function(obj) {
6326 each(slice.call(arguments, 1), function(source) {
6327 if (source) {
6328 for (var prop in source) {
6329 obj[prop] = source[prop];
6330 }
6331 }
6332 });
6333 return obj;
6334 };
6335
6336 // Return a copy of the object only containing the whitelisted properties.
6337 _.pick = function(obj) {
6338 var copy = {};
6339 var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
6340 each(keys, function(key) {
6341 if (key in obj) copy[key] = obj[key];
6342 });
6343 return copy;
6344 };
6345
6346 // Return a copy of the object without the blacklisted properties.
6347 _.omit = function(obj) {
6348 var copy = {};
6349 var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
6350 for (var key in obj) {
6351 if (!_.contains(keys, key)) copy[key] = obj[key];
6352 }
6353 return copy;
6354 };
6355
6356 // Fill in a given object with default properties.
6357 _.defaults = function(obj) {
6358 each(slice.call(arguments, 1), function(source) {
6359 if (source) {
6360 for (var prop in source) {
6361 if (obj[prop] == null) obj[prop] = source[prop];
6362 }
6363 }
6364 });
6365 return obj;
6366 };
6367
6368 // Create a (shallow-cloned) duplicate of an object.
6369 _.clone = function(obj) {
6370 if (!_.isObject(obj)) return obj;
6371 return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
6372 };
6373
6374 // Invokes interceptor with the obj, and then returns obj.
6375 // The primary purpose of this method is to "tap into" a method chain, in
6376 // order to perform operations on intermediate results within the chain.
6377 _.tap = function(obj, interceptor) {
6378 interceptor(obj);
6379 return obj;
6380 };
6381
6382 // Internal recursive comparison function for `isEqual`.
6383 var eq = function(a, b, aStack, bStack) {
6384 // Identical objects are equal. `0 === -0`, but they aren't identical.
6385 // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
6386 if (a === b) return a !== 0 || 1 / a == 1 / b;
6387 // A strict comparison is necessary because `null == undefined`.
6388 if (a == null || b == null) return a === b;
6389 // Unwrap any wrapped objects.
6390 if (a instanceof _) a = a._wrapped;
6391 if (b instanceof _) b = b._wrapped;
6392 // Compare `[[Class]]` names.
6393 var className = toString.call(a);
6394 if (className != toString.call(b)) return false;
6395 switch (className) {
6396 // Strings, numbers, dates, and booleans are compared by value.
6397 case '[object String]':
6398 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
6399 // equivalent to `new String("5")`.
6400 return a == String(b);
6401 case '[object Number]':
6402 // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
6403 // other numeric values.
6404 return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
6405 case '[object Date]':
6406 case '[object Boolean]':
6407 // Coerce dates and booleans to numeric primitive values. Dates are compared by their
6408 // millisecond representations. Note that invalid dates with millisecond representations
6409 // of `NaN` are not equivalent.
6410 return +a == +b;
6411 // RegExps are compared by their source patterns and flags.
6412 case '[object RegExp]':
6413 return a.source == b.source &&
6414 a.global == b.global &&
6415 a.multiline == b.multiline &&
6416 a.ignoreCase == b.ignoreCase;
6417 }
6418 if (typeof a != 'object' || typeof b != 'object') return false;
6419 // Assume equality for cyclic structures. The algorithm for detecting cyclic
6420 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
6421 var length = aStack.length;
6422 while (length--) {
6423 // Linear search. Performance is inversely proportional to the number of
6424 // unique nested structures.
6425 if (aStack[length] == a) return bStack[length] == b;
6426 }
6427 // Add the first object to the stack of traversed objects.
6428 aStack.push(a);
6429 bStack.push(b);
6430 var size = 0, result = true;
6431 // Recursively compare objects and arrays.
6432 if (className == '[object Array]') {
6433 // Compare array lengths to determine if a deep comparison is necessary.
6434 size = a.length;
6435 result = size == b.length;
6436 if (result) {
6437 // Deep compare the contents, ignoring non-numeric properties.
6438 while (size--) {
6439 if (!(result = eq(a[size], b[size], aStack, bStack))) break;
6440 }
6441 }
6442 } else {
6443 // Objects with different constructors are not equivalent, but `Object`s
6444 // from different frames are.
6445 var aCtor = a.constructor, bCtor = b.constructor;
6446 if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
6447 _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
6448 return false;
6449 }
6450 // Deep compare objects.
6451 for (var key in a) {
6452 if (_.has(a, key)) {
6453 // Count the expected number of properties.
6454 size++;
6455 // Deep compare each member.
6456 if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
6457 }
6458 }
6459 // Ensure that both objects contain the same number of properties.
6460 if (result) {
6461 for (key in b) {
6462 if (_.has(b, key) && !(size--)) break;
6463 }
6464 result = !size;
6465 }
6466 }
6467 // Remove the first object from the stack of traversed objects.
6468 aStack.pop();
6469 bStack.pop();
6470 return result;
6471 };
6472
6473 // Perform a deep comparison to check if two objects are equal.
6474 _.isEqual = function(a, b) {
6475 return eq(a, b, [], []);
6476 };
6477
6478 // Is a given array, string, or object empty?
6479 // An "empty" object has no enumerable own-properties.
6480 _.isEmpty = function(obj) {
6481 if (obj == null) return true;
6482 if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
6483 for (var key in obj) if (_.has(obj, key)) return false;
6484 return true;
6485 };
6486
6487 // Is a given value a DOM element?
6488 _.isElement = function(obj) {
6489 return !!(obj && obj.nodeType === 1);
6490 };
6491
6492 // Is a given value an array?
6493 // Delegates to ECMA5's native Array.isArray
6494 _.isArray = nativeIsArray || function(obj) {
6495 return toString.call(obj) == '[object Array]';
6496 };
6497
6498 // Is a given variable an object?
6499 _.isObject = function(obj) {
6500 return obj === Object(obj);
6501 };
6502
6503 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
6504 each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
6505 _['is' + name] = function(obj) {
6506 return toString.call(obj) == '[object ' + name + ']';
6507 };
6508 });
6509
6510 // Define a fallback version of the method in browsers (ahem, IE), where
6511 // there isn't any inspectable "Arguments" type.
6512 if (!_.isArguments(arguments)) {
6513 _.isArguments = function(obj) {
6514 return !!(obj && _.has(obj, 'callee'));
6515 };
6516 }
6517
6518 // Optimize `isFunction` if appropriate.
6519 if (typeof (/./) !== 'function') {
6520 _.isFunction = function(obj) {
6521 return typeof obj === 'function';
6522 };
6523 }
6524
6525 // Is a given object a finite number?
6526 _.isFinite = function(obj) {
6527 return isFinite(obj) && !isNaN(parseFloat(obj));
6528 };
6529
6530 // Is the given value `NaN`? (NaN is the only number which does not equal itself).
6531 _.isNaN = function(obj) {
6532 return _.isNumber(obj) && obj != +obj;
6533 };
6534
6535 // Is a given value a boolean?
6536 _.isBoolean = function(obj) {
6537 return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
6538 };
6539
6540 // Is a given value equal to null?
6541 _.isNull = function(obj) {
6542 return obj === null;
6543 };
6544
6545 // Is a given variable undefined?
6546 _.isUndefined = function(obj) {
6547 return obj === void 0;
6548 };
6549
6550 // Shortcut function for checking if an object has a given property directly
6551 // on itself (in other words, not on a prototype).
6552 _.has = function(obj, key) {
6553 return hasOwnProperty.call(obj, key);
6554 };
6555
6556 // Utility Functions
6557 // -----------------
6558
6559 // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
6560 // previous owner. Returns a reference to the Underscore object.
6561 _.noConflict = function() {
6562 root._ = previousUnderscore;
6563 return this;
6564 };
6565
6566 // Keep the identity function around for default iterators.
6567 _.identity = function(value) {
6568 return value;
6569 };
6570
6571 // Run a function **n** times.
6572 _.times = function(n, iterator, context) {
6573 var accum = Array(n);
6574 for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
6575 return accum;
6576 };
6577
6578 // Return a random integer between min and max (inclusive).
6579 _.random = function(min, max) {
6580 if (max == null) {
6581 max = min;
6582 min = 0;
6583 }
6584 return min + Math.floor(Math.random() * (max - min + 1));
6585 };
6586
6587 // List of HTML entities for escaping.
6588 var entityMap = {
6589 escape: {
6590 '&': '&amp;',
6591 '<': '&lt;',
6592 '>': '&gt;',
6593 '"': '&quot;',
6594 "'": '&#x27;',
6595 '/': '&#x2F;'
6596 }
6597 };
6598 entityMap.unescape = _.invert(entityMap.escape);
6599
6600 // Regexes containing the keys and values listed immediately above.
6601 var entityRegexes = {
6602 escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
6603 unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
6604 };
6605
6606 // Functions for escaping and unescaping strings to/from HTML interpolation.
6607 _.each(['escape', 'unescape'], function(method) {
6608 _[method] = function(string) {
6609 if (string == null) return '';
6610 return ('' + string).replace(entityRegexes[method], function(match) {
6611 return entityMap[method][match];
6612 });
6613 };
6614 });
6615
6616 // If the value of the named property is a function then invoke it;
6617 // otherwise, return it.
6618 _.result = function(object, property) {
6619 if (object == null) return null;
6620 var value = object[property];
6621 return _.isFunction(value) ? value.call(object) : value;
6622 };
6623
6624 // Add your own custom functions to the Underscore object.
6625 _.mixin = function(obj) {
6626 each(_.functions(obj), function(name){
6627 var func = _[name] = obj[name];
6628 _.prototype[name] = function() {
6629 var args = [this._wrapped];
6630 push.apply(args, arguments);
6631 return result.call(this, func.apply(_, args));
6632 };
6633 });
6634 };
6635
6636 // Generate a unique integer id (unique within the entire client session).
6637 // Useful for temporary DOM ids.
6638 var idCounter = 0;
6639 _.uniqueId = function(prefix) {
6640 var id = ++idCounter + '';
6641 return prefix ? prefix + id : id;
6642 };
6643
6644 // By default, Underscore uses ERB-style template delimiters, change the
6645 // following template settings to use alternative delimiters.
6646 _.templateSettings = {
6647 evaluate : /<%([\s\S]+?)%>/g,
6648 interpolate : /<%=([\s\S]+?)%>/g,
6649 escape : /<%-([\s\S]+?)%>/g
6650 };
6651
6652 // When customizing `templateSettings`, if you don't want to define an
6653 // interpolation, evaluation or escaping regex, we need one that is
6654 // guaranteed not to match.
6655 var noMatch = /(.)^/;
6656
6657 // Certain characters need to be escaped so that they can be put into a
6658 // string literal.
6659 var escapes = {
6660 "'": "'",
6661 '\\': '\\',
6662 '\r': 'r',
6663 '\n': 'n',
6664 '\t': 't',
6665 '\u2028': 'u2028',
6666 '\u2029': 'u2029'
6667 };
6668
6669 var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
6670
6671 // JavaScript micro-templating, similar to John Resig's implementation.
6672 // Underscore templating handles arbitrary delimiters, preserves whitespace,
6673 // and correctly escapes quotes within interpolated code.
6674 _.template = function(text, data, settings) {
6675 var render;
6676 settings = _.defaults({}, settings, _.templateSettings);
6677
6678 // Combine delimiters into one regular expression via alternation.
6679 var matcher = new RegExp([
6680 (settings.escape || noMatch).source,
6681 (settings.interpolate || noMatch).source,
6682 (settings.evaluate || noMatch).source
6683 ].join('|') + '|$', 'g');
6684
6685 // Compile the template source, escaping string literals appropriately.
6686 var index = 0;
6687 var source = "__p+='";
6688 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
6689 source += text.slice(index, offset)
6690 .replace(escaper, function(match) { return '\\' + escapes[match]; });
6691
6692 if (escape) {
6693 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
6694 }
6695 if (interpolate) {
6696 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
6697 }
6698 if (evaluate) {
6699 source += "';\n" + evaluate + "\n__p+='";
6700 }
6701 index = offset + match.length;
6702 return match;
6703 });
6704 source += "';\n";
6705
6706 // If a variable is not specified, place data values in local scope.
6707 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
6708
6709 source = "var __t,__p='',__j=Array.prototype.join," +
6710 "print=function(){__p+=__j.call(arguments,'');};\n" +
6711 source + "return __p;\n";
6712
6713 try {
6714 render = new Function(settings.variable || 'obj', '_', source);
6715 } catch (e) {
6716 e.source = source;
6717 throw e;
6718 }
6719
6720 if (data) return render(data, _);
6721 var template = function(data) {
6722 return render.call(this, data, _);
6723 };
6724
6725 // Provide the compiled function source as a convenience for precompilation.
6726 template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
6727
6728 return template;
6729 };
6730
6731 // Add a "chain" function, which will delegate to the wrapper.
6732 _.chain = function(obj) {
6733 return _(obj).chain();
6734 };
6735
6736 // OOP
6737 // ---------------
6738 // If Underscore is called as a function, it returns a wrapped object that
6739 // can be used OO-style. This wrapper holds altered versions of all the
6740 // underscore functions. Wrapped objects may be chained.
6741
6742 // Helper function to continue chaining intermediate results.
6743 var result = function(obj) {
6744 return this._chain ? _(obj).chain() : obj;
6745 };
6746
6747 // Add all of the Underscore functions to the wrapper object.
6748 _.mixin(_);
6749
6750 // Add all mutator Array functions to the wrapper.
6751 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
6752 var method = ArrayProto[name];
6753 _.prototype[name] = function() {
6754 var obj = this._wrapped;
6755 method.apply(obj, arguments);
6756 if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
6757 return result.call(this, obj);
6758 };
6759 });
6760
6761 // Add all accessor Array functions to the wrapper.
6762 each(['concat', 'join', 'slice'], function(name) {
6763 var method = ArrayProto[name];
6764 _.prototype[name] = function() {
6765 return result.call(this, method.apply(this._wrapped, arguments));
6766 };
6767 });
6768
6769 _.extend(_.prototype, {
6770
6771 // Start chaining a wrapped Underscore object.
6772 chain: function() {
6773 this._chain = true;
6774 return this;
6775 },
6776
6777 // Extracts the result from a wrapped and chained object.
6778 value: function() {
6779 return this._wrapped;
6780 }
6781
6782 });
6783
6784}).call(this);
6785
6786})()
6787},{}],21:[function(require,module,exports){
6788window.requestAnimFrame = (function() {
6789 return window.requestAnimationFrame ||
6790 window.webkitRequestAnimationFrame ||
6791 window.mozRequestAnimationFrame ||
6792 window.oRequestAnimationFrame ||
6793 window.msRequestAnimationFrame ||
6794 function(callback) { window.setTimeout(callback, 1000 / 60); }
6795})();
6796
6797Leap = require("../lib/index");
6798
6799},{"../lib/index":8}]},{},[21])
6800;
\No newline at end of file