aframe-video-controls
Version:
Video Controls for video assets
1,611 lines (1,252 loc) • 1.47 MB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
!function(t){function e(a){if(i[a])return i[a].exports;var s=i[a]={exports:{},id:a,loaded:!1};return t[a].call(s.exports,s,s.exports,e),s.loaded=!0,s.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e){if("undefined"==typeof AFRAME)throw new Error("Component attempted to register before AFRAME was available.");var i="Double-click outside player to hide or show it.",a="Look+click on play or bar. Space bar and arrows also work.";AFRAME.registerComponent("video-controls",{schema:{src:{type:"string"},size:{type:"number","default":1},distance:{type:"number","default":2},backgroundColor:{"default":"black"},barColor:{"default":"red"},textColor:{"default":"yellow"},infoTextBottom:{"default":i},infoTextTop:{"default":a},infoTextFont:{"default":"35px Helvetica Neue"},statusTextFont:{"default":"30px Helvetica Neue"},timeTextFont:{"default":"70px Helvetica Neue"}},position_time_from_steps:function(){var t=this.current_step/this.bar_steps;this.video_el.readyState>0&&(this.video_el.currentTime=t*this.video_el.duration)},position_control_from_camera:function(){for(var t=this,e=document.querySelectorAll("a-camera"),i=0;i<e.length;i++){var a=e[i];if(a.getAttribute("camera").active){var s=a.object3D.getWorldDirection().projectOnPlane(new THREE.Vector3(0,1,0)).setLength(t.data.distance);t.el.object3D.position.copy(a.object3D.getWorldPosition().sub(s)),t.el.object3D.lookAt(a.object3D.getWorldPosition())}}},init:function(){var t=this;this.bar_steps=10,this.current_step=0,this.el.setAttribute("visible",!0),this.video_selector=this.data.src,this.video_el=document.querySelector(this.video_selector),this.video_el.pause(),this.video_el.addEventListener("ended",function(){t.play_image.setAttribute("src","#video-play-image")}),this.play_image=document.createElement("a-image"),this.play_image.setAttribute("src","#video-play-image"),this.bar_canvas=document.createElement("canvas"),this.bar_canvas.setAttribute("id","video_player_canvas"),this.bar_canvas.width=1024,this.bar_canvas.height=256,this.bar_canvas.style.display="none",this.context=this.bar_canvas.getContext("2d"),this.texture=new THREE.Texture(this.bar_canvas),this.play_image.addEventListener("click",function(e){t.video_el.paused?(this.setAttribute("src","#video-pause-image"),t.video_el.play()):(this.setAttribute("src","#video-play-image"),t.video_el.pause()),e.stopPropagation(),e.preventDefault()}),window.addEventListener("keyup",function(e){switch(e.keyCode){case 32:t.play_image.dispatchEvent(new Event("click"));break;case 37:t.current_step=0,t.position_time_from_steps();break;case 39:t.current_step=t.bar_steps,t.position_time_from_steps();break;case 38:t.current_step=t.current_step<t.bar_steps?t.current_step+1:t.current_step,t.position_time_from_steps();break;case 40:t.current_step=t.current_step>0?t.current_step-1:t.current_step,t.position_time_from_steps()}},!1),this.bar=document.createElement("a-plane"),this.bar.setAttribute("color","#000"),this.bar.addEventListener("click",function(e){var i=document.querySelector("a-cursor").components.raycaster.raycaster.intersectObject(this.object3D,!0)[0].point,a=this.object3D.worldToLocal(i).x,s=a/t.data.size+.5;t.current_step=Math.round(s*t.bar_steps),t.video_el.readyState>0&&(t.video_el.currentTime=s*t.video_el.duration),e.stopPropagation(),e.preventDefault()}),this.el.appendChild(this.bar_canvas),this.el.appendChild(this.play_image),this.el.appendChild(this.bar),this.el.sceneEl.addEventListener("loaded",function(){t.position_control_from_camera(),this.addEventListener("dblclick",function(){var e=document.querySelector("a-cursor").components.raycaster.raycaster;0==e.intersectObject(t.el.object3D,!0).length&&(t.el.getAttribute("visible")?t.el.setAttribute("visible",!1):(t.el.setAttribute("visible",!0),t.position_control_from_camera()))})})},update:function(t){this.position_control_from_camera(),this.bar.setAttribute("height",this.data.size/4),this.bar.setAttribute("width",this.data.size),this.bar.setAttribute("position","0.0 0.0 0"),this.play_image.setAttribute("height",this.data.size/4),this.play_image.setAttribute("width",this.data.size/4),this.play_image.setAttribute("position",-this.data.size/2*1.4+" 0 0")},remove:function(){},tick:function(t){if("undefined"==typeof this.last_time||t-this.last_time>250){if(this.video_el.readyState>0){var e=Math.floor(this.video_el.currentTime/60),i=Math.floor(this.video_el.currentTime%60);e=e<10?"0"+e:e,i=i<10?"0"+i:i;var a=Math.floor(this.video_el.duration/60),s=Math.floor(this.video_el.duration%60);a=a<10?"0"+a:a,s=s<10?"0"+s:s;var r=e+":"+i+" / "+a+":"+s,o=this.bar_canvas.width/this.video_el.duration;if(this.video_el.buffered.length>0){this.current_step=Math.round(this.video_el.currentTime/this.video_el.duration*this.bar_steps);var n=this.context;if(n.fillStyle=this.data.backgroundColor,n.fillRect(0,0,this.bar_canvas.width,this.bar_canvas.height),n.font=this.data.timeTextFont,n.fillStyle="white",n.textAlign="center",n.fillText(r,this.bar_canvas.width/2,.65*this.bar_canvas.height),this.video_el.seeking)n.font=this.data.statusTextFont,n.fillStyle=this.data.textColor,n.textAlign="end",n.fillText("Seeking",.95*this.bar_canvas.width,.6*this.bar_canvas.height);else{var l=this.video_el.buffered.end(this.video_el.buffered.length-1)/this.video_el.duration*100;n.font=this.data.statusTextFont,n.fillStyle=this.data.textColor,n.textAlign="end",n.fillText(l.toFixed(0)+"% loaded",.95*this.bar_canvas.width,.6*this.bar_canvas.height)}n.fillStyle=this.data.textColor,n.font=this.data.infoTextFont,n.textAlign="center",n.fillText(this.data.infoTextTop,this.bar_canvas.width/2,.8*this.bar_canvas.height),n.fillText(this.data.infoTextBottom,this.bar_canvas.width/2,.95*this.bar_canvas.height);for(var h=0;h<this.video_el.buffered.length;h++){var c=this.video_el.buffered.start(h)*o,d=this.video_el.buffered.end(h)*o,u=d-c;n.fillStyle="grey",n.fillRect(c,0,u,this.bar_canvas.height/3)}n.fillStyle=this.data.barColor,n.fillRect(0,0,this.video_el.currentTime/this.video_el.duration*this.bar_canvas.width,this.bar_canvas.height/3)}this.bar.object3D.children.length>0&&(null===this.bar.object3D.children[0].material.map&&(this.bar.object3D.children[0].material=new THREE.MeshBasicMaterial,this.bar.object3D.children[0].material.map=this.texture),this.texture.needsUpdate=!0)}this.last_time=t}},pause:function(){},play:function(){}})}]);
},{}],2:[function(require,module,exports){
require('aframe');
require('../index.js');
},{"../index.js":1,"aframe":3}],3:[function(require,module,exports){
(function (global){
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.AFRAME = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
'use strict';
// For more information about browser field, check out the browser field at https://github.com/substack/browserify-handbook#browser-field.
module.exports = {
// Create a <link> tag with optional data attributes
createLink: function(href, attributes) {
var head = document.head || document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.href = href;
link.rel = 'stylesheet';
for (var key in attributes) {
if ( ! attributes.hasOwnProperty(key)) {
continue;
}
var value = attributes[key];
link.setAttribute('data-' + key, value);
}
head.appendChild(link);
},
// Create a <style> tag with optional data attributes
createStyle: function(cssText, attributes) {
var head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
style.type = 'text/css';
for (var key in attributes) {
if ( ! attributes.hasOwnProperty(key)) {
continue;
}
var value = attributes[key];
style.setAttribute('data-' + key, value);
}
if (style.sheet) { // for jsdom and IE9+
style.innerHTML = cssText;
style.sheet.cssText = cssText;
head.appendChild(style);
} else if (style.styleSheet) { // for IE8 and below
head.appendChild(style);
style.styleSheet.cssText = cssText;
} else { // for Chrome, Firefox, and Safari
style.appendChild(document.createTextNode(cssText));
head.appendChild(style);
}
}
};
},{}],2:[function(_dereq_,module,exports){
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = setTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
clearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue, 0);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}],3:[function(_dereq_,module,exports){
/**
* This is the web browser implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = _dereq_('./debug');
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = 'undefined' != typeof chrome
&& 'undefined' != typeof chrome.storage
? chrome.storage.local
: localstorage();
/**
* Colors.
*/
exports.colors = [
'lightseagreen',
'forestgreen',
'goldenrod',
'dodgerblue',
'darkorchid',
'crimson'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
function useColors() {
// is webkit? http://stackoverflow.com/a/16459606/376773
return ('WebkitAppearance' in document.documentElement.style) ||
// is firebug? http://stackoverflow.com/a/398120/376773
(window.console && (console.firebug || (console.exception && console.table))) ||
// is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
}
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
exports.formatters.j = function(v) {
return JSON.stringify(v);
};
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs() {
var args = arguments;
var useColors = this.useColors;
args[0] = (useColors ? '%c' : '')
+ this.namespace
+ (useColors ? ' %c' : ' ')
+ args[0]
+ (useColors ? '%c ' : ' ')
+ '+' + exports.humanize(this.diff);
if (!useColors) return args;
var c = 'color: ' + this.color;
args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
args[0].replace(/%[a-z%]/g, function(match) {
if ('%%' === match) return;
index++;
if ('%c' === match) {
// we only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
return args;
}
/**
* Invokes `console.log()` when available.
* No-op when `console.log` is not a "function".
*
* @api public
*/
function log() {
// this hackery is required for IE8/9, where
// the `console.log` function doesn't have 'apply'
return 'object' === typeof console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (null == namespaces) {
exports.storage.removeItem('debug');
} else {
exports.storage.debug = namespaces;
}
} catch(e) {}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
var r;
try {
r = exports.storage.debug;
} catch(e) {}
return r;
}
/**
* Enable namespaces listed in `localStorage.debug` initially.
*/
exports.enable(load());
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage(){
try {
return window.localStorage;
} catch (e) {}
}
},{"./debug":4}],4:[function(_dereq_,module,exports){
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = _dereq_('ms');
/**
* The currently active debug mode names, and names to skip.
*/
exports.names = [];
exports.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lowercased letter, i.e. "n".
*/
exports.formatters = {};
/**
* Previously assigned color.
*/
var prevColor = 0;
/**
* Previous log timestamp.
*/
var prevTime;
/**
* Select a color.
*
* @return {Number}
* @api private
*/
function selectColor() {
return exports.colors[prevColor++ % exports.colors.length];
}
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function debug(namespace) {
// define the `disabled` version
function disabled() {
}
disabled.enabled = false;
// define the `enabled` version
function enabled() {
var self = enabled;
// set `diff` timestamp
var curr = +new Date();
var ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
// add the `color` if not set
if (null == self.useColors) self.useColors = exports.useColors();
if (null == self.color && self.useColors) self.color = selectColor();
var args = Array.prototype.slice.call(arguments);
args[0] = exports.coerce(args[0]);
if ('string' !== typeof args[0]) {
// anything else let's inspect with %o
args = ['%o'].concat(args);
}
// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = exports.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);
// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
if ('function' === typeof exports.formatArgs) {
args = exports.formatArgs.apply(self, args);
}
var logFn = enabled.log || exports.log || console.log.bind(console);
logFn.apply(self, args);
}
enabled.enabled = true;
var fn = exports.enabled(namespace) ? enabled : disabled;
fn.namespace = namespace;
return fn;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
exports.save(namespaces);
var split = (namespaces || '').split(/[\s,]+/);
var len = split.length;
for (var i = 0; i < len; i++) {
if (!split[i]) continue; // ignore empty strings
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
exports.names.push(new RegExp('^' + namespaces + '$'));
}
}
}
/**
* Disable debug output.
*
* @api public
*/
function disable() {
exports.enable('');
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
var i, len;
for (i = 0, len = exports.skips.length; i < len; i++) {
if (exports.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = exports.names.length; i < len; i++) {
if (exports.names[i].test(name)) {
return true;
}
}
return false;
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
},{"ms":5}],5:[function(_dereq_,module,exports){
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} options
* @return {String|Number}
* @api public
*/
module.exports = function(val, options){
options = options || {};
if ('string' == typeof val) return parse(val);
return options.long
? long(val)
: short(val);
};
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
str = '' + str;
if (str.length > 10000) return;
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
if (!match) return;
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'yrs':
case 'yr':
case 'y':
return n * y;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'hrs':
case 'hr':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'mins':
case 'min':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 'secs':
case 'sec':
case 's':
return n * s;
case 'milliseconds':
case 'millisecond':
case 'msecs':
case 'msec':
case 'ms':
return n;
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function short(ms) {
if (ms >= d) return Math.round(ms / d) + 'd';
if (ms >= h) return Math.round(ms / h) + 'h';
if (ms >= m) return Math.round(ms / m) + 'm';
if (ms >= s) return Math.round(ms / s) + 's';
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function long(ms) {
return plural(ms, d, 'day')
|| plural(ms, h, 'hour')
|| plural(ms, m, 'minute')
|| plural(ms, s, 'second')
|| ms + ' ms';
}
/**
* Pluralization helper.
*/
function plural(ms, n, name) {
if (ms < n) return;
if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
return Math.ceil(ms / n) + ' ' + name + 's';
}
},{}],6:[function(_dereq_,module,exports){
'use strict';
var isObj = _dereq_('is-obj');
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === undefined) {
throw new TypeError('Sources cannot be null or undefined');
}
return Object(val);
}
function assignKey(to, from, key) {
var val = from[key];
if (val === undefined || val === null) {
return;
}
if (hasOwnProperty.call(to, key)) {
if (to[key] === undefined || to[key] === null) {
throw new TypeError('Cannot convert undefined or null to object (' + key + ')');
}
}
if (!hasOwnProperty.call(to, key) || !isObj(val)) {
to[key] = val;
} else {
to[key] = assign(Object(to[key]), from[key]);
}
}
function assign(to, from) {
if (to === from) {
return to;
}
from = Object(from);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
assignKey(to, from, key);
}
}
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
assignKey(to, from, symbols[i]);
}
}
}
return to;
}
module.exports = function deepAssign(target) {
target = toObject(target);
for (var s = 1; s < arguments.length; s++) {
assign(target, arguments[s]);
}
return target;
};
},{"is-obj":7}],7:[function(_dereq_,module,exports){
'use strict';
module.exports = function (x) {
var type = typeof x;
return x !== null && (type === 'object' || type === 'function');
};
},{}],8:[function(_dereq_,module,exports){
/*! (C) WebReflection Mit Style License */
(function(t,n,r,i){"use strict";function st(e,t){for(var n=0,r=e.length;n<r;n++)gt(e[n],t)}function ot(e){for(var t=0,n=e.length,r;t<n;t++)r=e[t],it(r,w[at(r)])}function ut(e){return function(t){F(t)&&(gt(t,e),st(t.querySelectorAll(E),e))}}function at(e){var t=R.call(e,"is"),n=e.nodeName.toUpperCase(),r=x.call(b,t?m+t.toUpperCase():v+n);return t&&-1<r&&!ft(n,t)?-1:r}function ft(e,t){return-1<E.indexOf(e+'[is="'+t+'"]')}function lt(e){var t=e.currentTarget,n=e.attrChange,r=e.attrName,i=e.target;Y&&(!i||i===t)&&t.attributeChangedCallback&&r!=="style"&&e.prevValue!==e.newValue&&t.attributeChangedCallback(r,n===e[f]?null:e.prevValue,n===e[c]?null:e.newValue)}function ct(e){var t=ut(e);return function(e){$.push(t,e.target)}}function ht(e){G&&(G=!1,e.currentTarget.removeEventListener(p,ht)),st((e.target||n).querySelectorAll(E),e.detail===u?u:o),j&&vt()}function pt(e,t){var n=this;U.call(n,e,t),Z.call(n,{target:n})}function dt(e,t){P(e,t),nt?nt.observe(e,X):(Q&&(e.setAttribute=pt,e[s]=tt(e),e.addEventListener(d,Z)),e.addEventListener(h,lt)),e.createdCallback&&Y&&(e.created=!0,e.createdCallback(),e.created=!1)}function vt(){for(var e,t=0,n=I.length;t<n;t++)e=I[t],S.contains(e)||(n--,I.splice(t--,1),gt(e,u))}function mt(e){throw new Error("A "+e+" type is already registered")}function gt(e,t){var n,r=at(e);-1<r&&(rt(e,w[r]),r=0,t===o&&!e[o]?(e[u]=!1,e[o]=!0,r=1,j&&x.call(I,e)<0&&I.push(e)):t===u&&!e[u]&&(e[o]=!1,e[u]=!0,r=1),r&&(n=e[t+"Callback"])&&n.call(e))}if(i in n)return;var s="__"+i+(Math.random()*1e5>>0),o="attached",u="detached",a="extends",f="ADDITION",l="MODIFICATION",c="REMOVAL",h="DOMAttrModified",p="DOMContentLoaded",d="DOMSubtreeModified",v="<",m="=",g=/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/,y=["ANNOTATION-XML","COLOR-PROFILE","FONT-FACE","FONT-FACE-SRC","FONT-FACE-URI","FONT-FACE-FORMAT","FONT-FACE-NAME","MISSING-GLYPH"],b=[],w=[],E="",S=n.documentElement,x=b.indexOf||function(e){for(var t=this.length;t--&&this[t]!==e;);return t},T=r.prototype,N=T.hasOwnProperty,C=T.isPrototypeOf,k=r.defineProperty,L=r.getOwnPropertyDescriptor,A=r.getOwnPropertyNames,O=r.getPrototypeOf,M=r.setPrototypeOf,_=!!r.__proto__,D=r.create||function yt(e){return e?(yt.prototype=e,new yt):this},P=M||(_?function(e,t){return e.__proto__=t,e}:A&&L?function(){function e(e,t){for(var n,r=A(t),i=0,s=r.length;i<s;i++)n=r[i],N.call(e,n)||k(e,n,L(t,n))}return function(t,n){do e(t,n);while((n=O(n))&&!C.call(n,t));return t}}():function(e,t){for(var n in t)e[n]=t[n];return e}),H=t.MutationObserver||t.WebKitMutationObserver,B=(t.HTMLElement||t.Element||t.Node).prototype,j=!C.call(B,S),F=j?function(e){return e.nodeType===1}:function(e){return C.call(B,e)},I=j&&[],q=B.cloneNode,R=B.getAttribute,U=B.setAttribute,z=B.removeAttribute,W=n.createElement,X=H&&{attributes:!0,characterData:!0,attributeOldValue:!0},V=H||function(e){Q=!1,S.removeEventListener(h,V)},$,J=t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.msRequestAnimationFrame||function(e){setTimeout(e,10)},K=!1,Q=!0,G=!0,Y=!0,Z,et,tt,nt,rt,it;M||_?(rt=function(e,t){C.call(t,e)||dt(e,t)},it=dt):(rt=function(e,t){e[s]||(e[s]=r(!0),dt(e,t))},it=rt),j?(Q=!1,function(){var t=L(B,"addEventListener"),n=t.value,r=function(e){var t=new CustomEvent(h,{bubbles:!0});t.attrName=e,t.prevValue=R.call(this,e),t.newValue=null,t[c]=t.attrChange=2,z.call(this,e),this.dispatchEvent(t)},i=function(t,n){var r=this.hasAttribute(t),i=r&&R.call(this,t);e=new CustomEvent(h,{bubbles:!0}),U.call(this,t,n),e.attrName=t,e.prevValue=r?i:null,e.newValue=n,r?e[l]=e.attrChange=1:e[f]=e.attrChange=0,this.dispatchEvent(e)},o=function(e){var t=e.currentTarget,n=t[s],r=e.propertyName,i;n.hasOwnProperty(r)&&(n=n[r],i=new CustomEvent(h,{bubbles:!0}),i.attrName=n.name,i.prevValue=n.value||null,i.newValue=n.value=t[r]||null,i.prevValue==null?i[f]=i.attrChange=0:i[l]=i.attrChange=1,t.dispatchEvent(i))};t.value=function(e,t,u){e===h&&this.attributeChangedCallback&&this.setAttribute!==i&&(this[s]={className:{name:"class",value:this.className}},this.setAttribute=i,this.removeAttribute=r,n.call(this,"propertychange",o)),n.call(this,e,t,u)},k(B,"addEventListener",t)}()):H||(S.addEventListener(h,V),S.setAttribute(s,1),S.removeAttribute(s),Q&&(Z=function(e){var t=this,n,r,i;if(t===e.target){n=t[s],t[s]=r=tt(t);for(i in r){if(!(i in n))return et(0,t,i,n[i],r[i],f);if(r[i]!==n[i])return et(1,t,i,n[i],r[i],l)}for(i in n)if(!(i in r))return et(2,t,i,n[i],r[i],c)}},et=function(e,t,n,r,i,s){var o={attrChange:e,currentTarget:t,attrName:n,prevValue:r,newValue:i};o[s]=e,lt(o)},tt=function(e){for(var t,n,r={},i=e.attributes,s=0,o=i.length;s<o;s++)t=i[s],n=t.name,n!=="setAttribute"&&(r[n]=t.value);return r})),n[i]=function(t,r){c=t.toUpperCase(),K||(K=!0,H?(nt=function(e,t){function n(e,t){for(var n=0,r=e.length;n<r;t(e[n++]));}return new H(function(r){for(var i,s,o,u=0,a=r.length;u<a;u++)i=r[u],i.type==="childList"?(n(i.addedNodes,e),n(i.removedNodes,t)):(s=i.target,Y&&s.attributeChangedCallback&&i.attributeName!=="style"&&(o=R.call(s,i.attributeName),o!==i.oldValue&&s.attributeChangedCallback(i.attributeName,i.oldValue,o)))})}(ut(o),ut(u)),nt.observe(n,{childList:!0,subtree:!0})):($=[],J(function d(){while($.length)$.shift().call(null,$.shift());J(d)}),n.addEventListener("DOMNodeInserted",ct(o)),n.addEventListener("DOMNodeRemoved",ct(u))),n.addEventListener(p,ht),n.addEventListener("readystatechange",ht),n.createElement=function(e,t){var r=W.apply(n,arguments),i=""+e,s=x.call(b,(t?m:v)+(t||i).toUpperCase()),o=-1<s;return t&&(r.setAttribute("is",t=t.toLowerCase()),o&&(o=ft(i.toUpperCase(),t))),Y=!n.createElement.innerHTMLHelper,o&&it(r,w[s]),r},B.cloneNode=function(e){var t=q.call(this,!!e),n=at(t);return-1<n&&it(t,w[n]),e&&ot(t.querySelectorAll(E)),t}),-2<x.call(b,m+c)+x.call(b,v+c)&&mt(t);if(!g.test(c)||-1<x.call(y,c))throw new Error("The type "+t+" is invalid");var i=function(){return f?n.createElement(l,c):n.createElement(l)},s=r||T,f=N.call(s,a),l=f?r[a].toUpperCase():c,c,h;return f&&-1<x.call(b,v+l)&&mt(l),h=b.push((f?m:v)+c)-1,E=E.concat(E.length?",":"",f?l+'[is="'+t.toLowerCase()+'"]':l),i.prototype=w[h]=N.call(s,"prototype")?s.prototype:D(B),st(n.querySelectorAll(E),o),i}})(window,document,Object,"registerElement");
},{}],9:[function(_dereq_,module,exports){
/* eslint-disable no-unused-vars */
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === undefined) {
throw new TypeError('Object.assign cannot be called with null or undefined');
}
return Object(val);
}
module.exports = Object.assign || function (target, source) {
var from;
var to = toObject(target);
var symbols;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
if (Object.getOwnPropertySymbols) {
symbols = Object.getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
};
},{}],10:[function(_dereq_,module,exports){
(function (global){
var performance = global.performance || {};
var present = (function () {
var names = ['now', 'webkitNow', 'msNow', 'mozNow', 'oNow'];
while (names.length) {
var name = names.shift();
if (name in performance) {
return performance[name].bind(performance);
}
}
var dateNow = Date.now || function () { return new Date().getTime(); };
var navigationStart = (performance.timing || {}).navigationStart || dateNow();
return function () {
return dateNow() - navigationStart;
};
}());
present.performanceNow = performance.now;
present.noConflict = function () {
performance.now = present.performanceNow;
};
present.conflict = function () {
performance.now = present;
};
present.conflict();
module.exports = present;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],11:[function(_dereq_,module,exports){
(function(root) {
// Store setTimeout reference so promise-polyfill will be unaffected by
// other code modifying setTimeout (like sinon.useFakeTimers())
var setTimeoutFunc = setTimeout;
// Use polyfill for setImmediate for performance gains
var asap = (typeof setImmediate === 'function' && setImmediate) ||
function(fn) { setTimeoutFunc(fn, 1); };
// Polyfill for Function.prototype.bind
function bind(fn, thisArg) {
return function() {
fn.apply(thisArg, arguments);
}
}
var isArray = Array.isArray || function(value) { return Object.prototype.toString.call(value) === "[object Array]" };
function Promise(fn) {
if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
if (typeof fn !== 'function') throw new TypeError('not a function');
this._state = null;
this._value = null;
this._deferreds = []
doResolve(fn, bind(resolve, this), bind(reject, this))
}
function handle(deferred) {
var me = this;
if (this._state === null) {
this._deferreds.push(deferred);
return
}
asap(function() {
var cb = me._state ? deferred.onFulfilled : deferred.onRejected
if (cb === null) {
(me._state ? deferred.resolve : deferred.reject)(me._value);
return;
}
var ret;
try {
ret = cb(me._value);
}
catch (e) {
deferred.reject(e);
return;
}
deferred.resolve(ret);
})
}
function resolve(newValue) {
try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === this) throw new TypeError('A promise cannot be resolved with itself.');
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then;
if (typeof then === 'function') {
doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
return;
}
}
this._state = true;
this._value = newValue;
finale.call(this);
} catch (e) { reject.call(this, e); }
}
function reject(newValue) {
this._state = false;
this._value = newValue;
finale.call(this);
}
function finale() {
for (var i = 0, len = this._deferreds.length; i < len; i++) {
handle.call(this, this._deferreds[i]);
}
this._deferreds = null;
}
function Handler(onFulfilled, onRejected, resolve, reject){
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
this.resolve = resolve;
this.reject = reject;
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
fn(function (value) {
if (done) return;
done = true;
onFulfilled(value);
}, function (reason) {
if (done) return;
done = true;
onRejected(reason);
})
} catch (ex) {
if (done) return;
done = true;
onRejected(ex);
}
}
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype.then = function(onFulfilled, onRejected) {
var me = this;
return new Promise(function(resolve, reject) {
handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
})
};
Promise.all = function () {
var args = Array.prototype.slice.call(arguments.length === 1 && isArray(arguments[0]) ? arguments[0] : arguments);
return new Promise(function (resolve, reject) {
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then;
if (typeof then === 'function') {
then.call(val, function (val) { res(i, val) }, reject);
return;
}
}
args[i] = val;
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex);
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
};
Promise.resolve = function (value) {
if (value && typeof value === 'object' && value.constructor === Promise) {
return value;
}
return new Promise(function (resolve) {
resolve(value);
});
};
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value);
});
};
Promise.race = function (values) {
return new Promise(function (resolve, reject) {
for(var i = 0, len = values.length; i < len; i++) {
values[i].then(resolve, reject);
}
});
};
/**
* Set the immediate function to execute callbacks
* @param fn {function} Function to execute
* @private
*/
Promise._setImmediateFn = function _setImmediateFn(fn) {
asap = fn;
};
if (typeof module !== 'undefined' && module.exports) {
module.exports = Promise;
} else if (!root.Promise) {
root.Promise = Promise;
}
})(this);
},{}],12:[function(_dereq_,module,exports){
'use strict';
var raf = _dereq_('raf');
var now = _dereq_('time-now');
exports = module.exports = interval;
function interval(delay, fn, ctx) {
var start = now();
var data = Object.create(null);
data.id = raf(loop);
return data;
function loop() {
data.id = raf(loop);
if ((now() - start) >= delay) {
fn.call(ctx);
start = now();
}
}
}
exports.clear = clearInterval;
function clearInterval(data) {
raf.cancel(data.id);
}
},{"raf":13,"time-now":14}],13:[function(_dereq_,module,exports){
/**
* Expose `requestAnimationFrame()`.
*/
exports = module.exports = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| fallback;
/**
* Fallback implementation.
*/
var prev = new Date().getTime();
function fallback(fn) {
var curr = new Date().getTime();
var ms = Math.max(0, 16 - (curr - prev));
var req = setTimeout(fn, ms);
prev = curr;
return req;
}
/**
* Cancel.
*/
var cancel = window.cancelAnimationFrame
|| window.webkitCancelAnimationFrame
|| window.mozCancelAnimationFrame
|| window.clearTimeout;
exports.cancel = function(id){
cancel.call(window, id);
};
},{}],14:[function(_dereq_,module,exports){
'use strict';
module.exports = (function() {
var perf = window && window.performance;
if (perf && perf.now) {
return perf.now.bind(perf);
} else {
return function() {
return new Date().getTime();
};
}
}());
},{}],15:[function(_dereq_,module,exports){
/*
style-attr
====
Very simple parsing and stringifying of style attributes.
`parse`
----
Convert a style attribute string to an object.
- input: string (eg. anything you might see in a style attribute)
- return: object
*/
function parse (raw) {
var trim = function (s) { return s.trim(); };
var obj = {};
getKeyValueChunks(raw)
.map(trim)
.filter(Boolean)
.forEach(function (item) {
// split with `.indexOf` rather than `.split` because the value may also contain colons.
var pos = item.indexOf(':');
var key = item.substr(0, pos).trim();
var val = item.substr(pos + 1).trim();
obj[key] = val;
});
return obj;
}
/*
`getKeyValueChunks`
----
Split a string into chunks matching `<key>: <value>`
- input: string
- return: Array<string>
*/
function getKeyValueChunks (raw) {
var chunks = [];
var offset = 0;
var sep = ';';
var hasUnclosedUrl = /url\([^\)]+$/;
var chunk = '';
var nextSplit;
while (offset < raw.length) {
nextSplit = raw.indexOf(sep, offset);
if (nextSplit === -1) { nextSplit = raw.length; }
chunk += raw.substring(offset, nextSplit);
// data URIs can contain semicolons, so make sure we get the whole thing
if (hasUnclosedUrl.test(chunk)) {
chunk += ';';
offset = nextSplit + 1;
continue;
}
chunks.push(chunk);
chunk = '';
offset = nextSplit + 1;
}
return chunks;
}
/*
`stringify`
----
Convert an object into an attribute string
- input: object
- return: string
*/
function stringify (obj) {
return Object.keys(obj)
.map(function (key) {
return key + ':' + obj[key];
})
.join(';');
}
/*
`normalize`
----
Normalize an attribute string (eg. collapse duplicates)
- input: string
- return: string
*/
function normalize (str) {
return stringify(parse(str));
}
module.exports.parse = parse;
module.exports.stringify = stringify;
module.exports.normalize = normalize;
},{}],16:[function(_dereq_,module,exports){
/**
* @author dmarcos / https://github.com/dmarcos
* @author mrdoob / http://mrdoob.com
*/
THREE.VRControls = function ( object, onError ) {
var scope = this;
var vrInputs = [];
function gotVRDevices( devices ) {
for ( var i = 0; i < devices.length; i ++ ) {
if ( devices[ i ] instanceof PositionSensorVRDevice ) {
vrInputs.push( devices[ i ] );
}
}
if ( vrInputs.length === 0 ) {
if ( onError ) onError( 'PositionSensorVRDevice not available' );
}
}
if ( navigator.getVRDevices ) {
navigator.getVRDevices().then( gotVRDevices );
}
// the Rift SDK returns the position in meters
// this scale factor allows the user to define how meters
// are converted to scene units.
this.scale = 1;
this.update = function () {
for ( var i = 0; i < vrInputs.length; i ++ ) {
var vrInput = vrInputs[ i ];
var state = vrInput.getState();
if ( state.orientation !== null ) {
object.quaternion.copy( state.orientation );
}
if ( state.position !== null ) {
object.position.copy( state.position ).multiplyScalar( scope.scale );
}
}
};
this.resetSensor = function () {
for ( var i = 0; i < vrInputs.length; i ++ ) {
var vrInput = vrInputs[ i ];
if ( vrInput.resetSensor !== undefined ) {
vrInput.resetSensor();
} else if ( vrInput.zeroSensor !== undefined ) {
vrInput.zeroSensor();
}
}
};
this.zeroSensor = function () {
console.warn( 'THREE.VRControls: .zeroSensor() is now .resetSensor().' );
this.resetSensor();
};
this.dispose = function () {
vrInputs = [];
};
};
},{}],17:[function(_dereq_,module,exports){
/**
* @author dmarcos / https://github.com/dmarcos
* @author mrdoob / http://mrdoob.com
*
* WebVR Spec: http://mozvr.github.io/webvr-spec/webvr.html
*
* Firefox: http://mozvr.com/downloads/
* Chromium: https://drive.google.com/folderview?id=0BzudLt22BqGRbW9WTHMtOWMzNjQ&usp=sharing#list
*
*/
THREE.VREffect = function ( renderer, onError ) {
var vrHMD;
var eyeTranslationL, eyeFOVL;
var eyeTranslationR, eyeFOVR;
function gotVRDevices( devices ) {
for ( var i = 0; i < devices.length; i ++ ) {
if ( devices[ i ] instanceof HMDVRDevice ) {
vrHMD = devices[ i ];
break; // We keep the first we encounter
}
}
if ( vrHMD === undefined ) {
if ( onError ) onError( 'HMD not available' );
}
}
if ( navigator.getVRDevices ) {
navigator.getVRDevices().then( gotVRDevices );
}
//
this.scale = 1;
this.setSize = function ( width, height ) {
renderer.setSize( width, height );
};
// fullscreen
var isFullscreen = false;
var canvas = renderer.domElement;
var fullscreenchange = canvas.mozRequestFullScreen ? 'mozfullscreenchange' : 'webkitfullscreenchange';
document.addEventListener( fullscreenchange, function ( event ) {
isFullscreen = document.mozFullScreenElement || document.webkitFullscreenElement;
}, false );
this.setFullScreen = function ( boolean ) {
if ( vrHMD === undefined ) return;
if ( isFullscreen === boolean ) return;
if ( canvas.mozRequestFullScreen ) {
canvas.mozRequestFullScreen( { vrDisplay: vrHMD } );
} else if ( canvas.webkitRequestFullscreen ) {
canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } );
}
};
// render
var cameraL = new THREE.PerspectiveCamera();
cameraL.layers.enable( 1 );
var cameraR = new THREE.PerspectiveCamera();
cameraR.layers.enable( 2 );
this.render = function ( scene, camera ) {
if ( vrHMD ) {
var eyeParamsL = vrHMD.getEyeParameters( 'left' );
var eyeParamsR = vrHMD.getEyeParameters( 'right' );
eyeTranslationL = eyeParamsL.eyeTranslation;
eyeTranslationR = eyeParamsR.eyeTranslation;
eyeFOVL = eyeParamsL.recommendedFieldOfView;
eyeFOVR = eyeParamsR.recommendedFieldOfView;
if ( Array.isArray( scene ) ) {
console.warn( 'THREE.VREffect.render() no longer supports arrays. Use object.layers instead.' );
scene = scene[ 0 ];
}
var size = renderer.getSize();
renderer.setScissorTest( true );
renderer.clear();
if ( camera.parent === null ) camera.updateMatrixWorld();
cameraL.projectionMatrix = fovToProjection( eyeFOVL, true, camera.near, camera.far );
cameraR.projectionMatrix = fovToProjection( eyeFOVR, true, camera.near, camera.far );
camera.matrixWorld.decompose( cameraL.position, cameraL.quaternion, cameraL.scale );
camera.matrixWorld.decompose( cameraR.position, cameraR.quaternion, cameraR.scale );
cameraL.translateX( eyeTranslationL.x * this.scale );
cameraR.translateX( eyeTranslationR.x * this.scale );
// render left eye
renderer.setViewport( 0, 0, size.width / 2, size.height );
renderer.setScissor( 0, 0, size.width / 2, size.height );
renderer.render( scene, cameraL );
// render right eye
renderer.setViewport( size.width / 2, 0, size.width / 2, size.height );
renderer.setScissor( size.width / 2, 0, size.width / 2, size.height );
renderer.render( scene, cameraR );
renderer.setScissorTest( false );
return;
}
// Regular render mode if not HMD
renderer.render( scene, camera );
};
//
function fovToNDCScaleOffset( fov ) {
var pxscale = 2.0 / ( fov.leftTan + fov.rightTan );
var pxoffset = ( fov.leftTan - fov.rightTan ) * pxscale * 0.5;
var pyscale = 2.0 / ( fov.upTan + fov.downTan );
var pyoffset = ( fov.upTan - fov.downTan ) * pyscale * 0.5;
return { scale: [ pxscale, pyscale ], offset: [ pxoffset, pyoffset ] };
}
function fovPortToProjection( fov, rightHanded, zNear, zFar ) {
rightHanded = rightHanded === undefined ? true : rightHanded;
zNear = zNear === undefined ? 0.01 : zNear;
zFar = zFar === undefined ? 10000.0 : zFar;
var handednessScale = rightHanded ? - 1.0 : 1.0;
// start with an identity matrix
var mobj = new THREE.Matrix4();
var m = mobj.elements;
// and with scale/offset info for normalized device coords
var scaleAndOffset = fovToNDCScaleOffset( fov );
// X result, map clip edges to [-w,+w]
m[ 0 * 4 + 0 ] = scaleAndOffset.scale[ 0 ];
m[ 0 * 4 + 1 ] = 0.0;
m[ 0 * 4 + 2 ] = scaleAndOffset.offset[ 0 ] * handednessScale;
m[ 0 * 4 + 3 ] = 0.0;
// Y result, map clip edges to [-w,+w]
// Y offset is negated because this proj matrix transforms from world coords with Y=up,
// but the NDC scaling has Y=down (thanks D3D?)
m[ 1 * 4 + 0 ] = 0.0;
m[ 1 * 4 + 1 ] = scaleAndOffset.scale[ 1 ];
m[ 1 * 4 + 2 ] = - scaleAndOffset.offset[ 1 ] * handednessScale;
m[ 1 * 4 + 3 ] = 0.0;
// Z result (up to the app)
m[ 2 * 4 + 0 ] = 0.0;
m[ 2 * 4 + 1 ] = 0.0;
m[ 2 * 4 + 2 ] = zFar / ( zNear - zFar ) * - handednessScale;
m[ 2 * 4 + 3 ] = ( zFar * zNear ) / ( zNear - zFar );
// W result (= Z in)
m[ 3 * 4 + 0 ] = 0.0;
m[ 3 * 4 + 1 ] = 0.0;
m[ 3 * 4 + 2 ] = handednessScale;
m[ 3 * 4 + 3 ] = 0.0;
mobj.transpose();
return mobj;
}
function fovToProjection( fov, rightHanded, zNear, zFar ) {
var DEG2RAD = Math.PI / 180.0;
var fovPort = {
upTan: Math.tan( fov.upDegrees * DEG2RAD ),
downTan: Math.tan( fov.downDegrees * DEG2RAD ),
leftTan: Math.tan( fov.leftDegrees * DEG2RAD ),
rightTan: Math.tan( fov.rightDegrees * DEG2RAD )
};
return fovPortToProjection( fovPort, rightHanded, zNear, zFar );
}
};
},{}],18:[function(_dereq_,module,exports){
/**
* @author Tim Knip / http://www.floorplanner.com/ / tim at floorplanner.com
* @author Tony Parisi / http://www.tonyparisi.com/
*/
THREE.ColladaLoader = function () {
var COLLADA = null;
var scene = null;
var visualScene;
var kinematicsModel;
var readyCallbackFunc = null;
var sources = {};
var images = {};
var animations = {};
var controllers = {};
var geometries = {};
var materials = {};
var effects = {};
var cameras = {};
var lights = {};
var animData;
var kinematics;
var visualScenes;
var kinematicsModels;
var baseUrl;
var morphs;
var skins;
var flip_uv = true;
var preferredShading = THREE.SmoothShading;
var options = {
// Force Geometry to always be centered at the local origin of the
// containing Mesh.
centerGeometry: false,
// Axis conversion is done for geometries, animations, and controllers.
// If we ever pull cameras or lights out of the COLLADA file, they'll
// need extra work.
convertUpAxis: false,
subdivideFaces: true,
upAxis: 'Y',
// For reflective or refractive materials we'll use this cubemap
defaultEnvMap: null
};
var colladaUnit = 1.0;
var colladaUp = 'Y';
var upConversion = null;
function load ( url, readyCallback, progressCallback, failCallback ) {
var length = 0;
if ( document.implementation && document.implementation.createDocument ) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if ( request.readyState === 4 ) {
if ( request.status === 0 || request.status === 200 ) {
if ( request.response ) {
readyCallbackFunc = readyCallback;
parse( request.response, undefined, url );
} else {
if ( failCallback ) {
failCallback();
} else {
console.error( "ColladaLoader: Empty or non-existing file (" + url + ")" );